├── .gitignore ├── LICENSE ├── MANIFEST.in ├── NEWS.rst ├── README.rst ├── lib ├── __init__.py ├── dbapi2.py ├── dump.py └── test │ ├── __init__.py │ ├── python2 │ ├── __init__.py │ ├── dbapi.py │ ├── dump.py │ ├── factory.py │ ├── hooks.py │ ├── regression.py │ ├── sqlcipher.py │ ├── transactions.py │ ├── types.py │ └── userfunctions.py │ └── python3 │ ├── __init__.py │ ├── dbapi.py │ ├── dump.py │ ├── factory.py │ ├── hooks.py │ ├── regression.py │ ├── sqlcipher.py │ ├── transactions.py │ ├── types.py │ └── userfunctions.py ├── setup.cfg ├── setup.py └── src ├── python2 ├── backup.h ├── cache.c ├── cache.h ├── connection.c ├── connection.h ├── cursor.c ├── cursor.h ├── microprotocols.c ├── microprotocols.h ├── module.c ├── module.h ├── prepare_protocol.c ├── prepare_protocol.h ├── row.c ├── row.h ├── sqlitecompat.h ├── statement.c ├── statement.h ├── util.c └── util.h └── python3 ├── cache.c ├── cache.h ├── connection.c ├── connection.h ├── cursor.c ├── cursor.h ├── microprotocols.c ├── microprotocols.h ├── module.c ├── module.h ├── prepare_protocol.c ├── prepare_protocol.h ├── row.c ├── row.h ├── statement.c ├── statement.h ├── util.c └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | # SQLCipher source files 2 | amalgamation/ 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | env/ 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | *.pot 47 | 48 | # Sphinx documentation 49 | docs/_build/ 50 | 51 | # PyBuilder 52 | target/ 53 | 54 | # PyCharm 55 | .idea/ 56 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) David Riggleman 2 | Copyright (C) Kali Kaneko 3 | Copyright (c) 2004-2007 Gerhard Häring 4 | 5 | This software is provided 'as-is', without any express or implied warranty. In 6 | no event will the authors be held liable for any damages arising from the use 7 | of this software. 8 | 9 | Permission is granted to anyone to use this software for any purpose, 10 | including commercial applications, and to alter it and redistribute it freely, 11 | subject to the following restrictions: 12 | 13 | 1. The origin of this software must not be misrepresented; you must not 14 | claim that you wrote the original software. If you use this software in 15 | a product, an acknowledgment in the product documentation would be 16 | appreciated but is not required. 17 | 18 | 2. Altered source versions must be plainly marked as such, and must not be 19 | misrepresented as being the original software. 20 | 21 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include README.rst 3 | include LICENSE 4 | include setup.py 5 | include src/*/*.h 6 | include src/*/*.c 7 | include lib/test/*/* 8 | 9 | global-exclude *~ *.pyc 10 | -------------------------------------------------------------------------------- /NEWS.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | Changes in pysqlcipher3 3 | ======================= 4 | Release 1.2.0 5 | ------------- 6 | * Add support for Python 3.11 7 | 8 | Release 1.1.0 9 | ------------- 10 | * Add support for Python 3.10 11 | 12 | Release 1.0.2 13 | ------------- 14 | * Fixed bug referencing dump.py (Python 2 only) 15 | * Added SQLCipher unit tests 16 | 17 | Release 1.0.1 18 | ------------- 19 | * Initial release. 20 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | pysqlcipher3 2 | ============ 3 | 4 | **Note: this project is no longer being actively maintained. Security vulnerabilities may exist in this code. Use at your own risk.** 5 | 6 | This library is a fork of pysqlcipher targeted for use with Python 3, 7 | although support for Python 2 is still maintained. It is still in the 8 | beta state, although this library contains minimal new code and 9 | instead heavily pulls from the core Python sqlite source code while 10 | linking against libsqlcipher. 11 | 12 | 13 | Original code (c) 2004-2007 Gerhard Häring 14 | 15 | Packaging for SQLCipher (c) 2013-2014 Kali Kaneko 16 | 17 | Python 3 packaging for SQLCipher (c) 2015 David Riggleman 18 | 19 | Usage 20 | ----- 21 | You have to pass the ``PRAGMA key`` before doing any operations:: 22 | 23 | from pysqlcipher3 import dbapi2 as sqlite 24 | conn = sqlite.connect('test.db') 25 | c = conn.cursor() 26 | c.execute("PRAGMA key='password'") 27 | c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''') 28 | c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""") 29 | conn.commit() 30 | c.close() 31 | 32 | You can quickly verify that your database file in indeed encrypted:: 33 | 34 | hexdump -C test.db 35 | ab 7f 61 7a 33 9d 07 f4 08 68 c9 b0 4f e3 34 60 |..az3....h..O.4`| 36 | bb 9d 9c 3d 9e ce 69 57 b6 2f 36 c4 fd 13 bd 61 |...=..iW./6....a| 37 | 77 bf e3 1d 65 b5 ea f7 d2 fc 98 31 23 66 a0 1e |w...e......1#f..| 38 | a4 4f fa 66 49 36 84 a1 3e 0c 21 98 84 07 eb 07 |.O.fI6..>.!.....| 39 | 40 | Build against libsqlcipher 41 | -------------------------- 42 | This is the default install option. For production use, you should build 43 | against ``libsqlcipher``, which must be installed on your system prior to 44 | installation. Consult your operating system documentation for how to 45 | install SQL Cipher. You can also manually build SQL Cipher by cloning 46 | https://github.com/sqlcipher/sqlcipher and following the build instructions. 47 | 48 | Build against amalgamation 49 | -------------------------- 50 | For convenience during development, you can use a sqlcipher amalgamation 51 | during the install. You will need to obtain the amalgamation from external 52 | sources or build it yourself from https://github.com/sqlcipher/sqlcipher. 53 | 54 | 55 | To build using the amalgamation, you can do it like this:: 56 | 57 | python setup.py build_amalgamation 58 | 59 | And then:: 60 | 61 | python setup.py install 62 | 63 | **32 Bit Windows Setup Instructions (using Visual Studio)** 64 | 65 | 1. **Install Visual Studio 2015**: if you do not have a paid license, the Community Edition will work fine. Make sure to select all the C++ options during the installation process. 66 | 67 | 2. **Install OpenSSL**: you can either download the source and build locally or install a prebuilt OpenSSL binary from https://slproweb.com/products/Win32OpenSSL.html (use the latest version) 68 | 69 | 3. **Confirm that the OPENSSL_CONF environment variable is set properly**: this should not be root OpenSSL path (ex: C:\\openssl-Win32), but instead should be the path to the config file (ex: C:\\openssl-Win32\\bin\\openssl.cfg) 70 | 71 | 4. **Copy the OpenSSL folder (C:\\openssl-Win32\\include\\openssl) to the VC include directory (ex: C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\include)**: confirm the following path exists (\\VC\\include\\openssl\\aes.h) 72 | 73 | 5. **Install the latest version of Python 3 (32-bit)**: if you have Python 64-bit installed, you may have to uninstall it before installing Python 32-bit. 74 | 75 | 6. **Use the SQL Cipher 3 amalgamation**: if needed, directions for building SQL Cipher can be found on the following tutorial: http://www.jerryrw.com/howtocompile.ph 76 | 77 | 7. **Follow the general instructions for building the amalgamation** 78 | 79 | **64 Bit Windows Setup Instructions (using Visual Studio)** 80 | 81 | Follow the same instructions as above except for the following: 82 | 83 | 1. **Make sure that you are using OpenSSL-Win64** 84 | 85 | 2. **Set the PATH to the Win64 environment** 86 | 87 | 3. **Copy the OpenSSL folder** 88 | 89 | 4. **Build the amalgamation and install with the latest Python x64** 90 | 91 | SQLCipher compatibility issues 92 | ---------------------------- 93 | The encryption has default compatibility with the SQLCipher version installed on your machine. 94 | You have to execute ``PRAGMA cipher_compatibility = 3`` before doing any operations on a database encrypted with SQLCipher version 3 when a newer version is installed. 95 | Keep in mind, you have to add ``PRAGMA cipher_compatibility`` after ``PRAGMA key``:: 96 | 97 | from pysqlcipher3 import dbapi2 as sqlite 98 | conn = sqlite.connect('test.db') 99 | c = conn.cursor() 100 | c.execute("PRAGMA key='password'") 101 | c.execute("PRAGMA cipher_compatibility = 3") 102 | c.execute('''create table stocks (date text, trans text, symbol text, qty real, price real)''') 103 | c.execute("""insert into stocks values ('2006-01-05','BUY','RHAT',100,35.14)""") 104 | conn.commit() 105 | c.close() -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | # pysqlite2/__init__.py: the pysqlite2 package. 2 | # 3 | # Copyright (C) 2005 Gerhard Häring 4 | # 5 | # This file is part of pysqlite. 6 | # 7 | # This software is provided 'as-is', without any express or implied 8 | # warranty. In no event will the authors be held liable for any damages 9 | # arising from the use of this software. 10 | # 11 | # Permission is granted to anyone to use this software for any purpose, 12 | # including commercial applications, and to alter it and redistribute it 13 | # freely, subject to the following restrictions: 14 | # 15 | # 1. The origin of this software must not be misrepresented; you must not 16 | # claim that you wrote the original software. If you use this software 17 | # in a product, an acknowledgment in the product documentation would be 18 | # appreciated but is not required. 19 | # 2. Altered source versions must be plainly marked as such, and must not be 20 | # misrepresented as being the original software. 21 | # 3. This notice may not be removed or altered from any source distribution. 22 | -------------------------------------------------------------------------------- /lib/dbapi2.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/dbapi2.py -------------------------------------------------------------------------------- /lib/dump.py: -------------------------------------------------------------------------------- 1 | # Mimic the sqlite3 console shell's .dump command 2 | # Author: Paul Kippes 3 | 4 | # Every identifier in sql is quoted based on a comment in sqlite 5 | # documentation "SQLite adds new keywords from time to time when it 6 | # takes on new features. So to prevent your code from being broken by 7 | # future enhancements, you should normally quote any identifier that 8 | # is an English language word, even if you do not have to." 9 | 10 | def _iterdump(connection): 11 | """ 12 | Returns an iterator to the dump of the database in an SQL text format. 13 | 14 | Used to produce an SQL dump of the database. Useful to save an in-memory 15 | database for later restoration. This function should not be called 16 | directly but instead called from the Connection method, iterdump(). 17 | """ 18 | 19 | cu = connection.cursor() 20 | yield('BEGIN TRANSACTION;') 21 | 22 | # sqlite_master table contains the SQL CREATE statements for the database. 23 | q = """ 24 | SELECT "name", "type", "sql" 25 | FROM "sqlite_master" 26 | WHERE "sql" NOT NULL AND 27 | "type" == 'table' 28 | ORDER BY "name" 29 | """ 30 | schema_res = cu.execute(q) 31 | for table_name, type, sql in schema_res.fetchall(): 32 | if table_name == 'sqlite_sequence': 33 | yield('DELETE FROM "sqlite_sequence";') 34 | elif table_name == 'sqlite_stat1': 35 | yield('ANALYZE "sqlite_master";') 36 | elif table_name.startswith('sqlite_'): 37 | continue 38 | # NOTE: Virtual table support not implemented 39 | #elif sql.startswith('CREATE VIRTUAL TABLE'): 40 | # qtable = table_name.replace("'", "''") 41 | # yield("INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"\ 42 | # "VALUES('table','{0}','{0}',0,'{1}');".format( 43 | # qtable, 44 | # sql.replace("''"))) 45 | else: 46 | yield('{0};'.format(sql)) 47 | 48 | # Build the insert statement for each row of the current table 49 | table_name_ident = table_name.replace('"', '""') 50 | res = cu.execute('PRAGMA table_info("{0}")'.format(table_name_ident)) 51 | column_names = [str(table_info[1]) for table_info in res.fetchall()] 52 | q = """SELECT 'INSERT INTO "{0}" VALUES({1})' FROM "{0}";""".format( 53 | table_name_ident, 54 | ",".join("""'||quote("{0}")||'""".format(col.replace('"', '""')) for col in column_names)) 55 | query_res = cu.execute(q) 56 | for row in query_res: 57 | yield("{0};".format(row[0])) 58 | 59 | # Now when the type is 'index', 'trigger', or 'view' 60 | q = """ 61 | SELECT "name", "type", "sql" 62 | FROM "sqlite_master" 63 | WHERE "sql" NOT NULL AND 64 | "type" IN ('index', 'trigger', 'view') 65 | """ 66 | schema_res = cu.execute(q) 67 | for name, type, sql in schema_res.fetchall(): 68 | yield('{0};'.format(sql)) 69 | 70 | yield('COMMIT;') 71 | -------------------------------------------------------------------------------- /lib/test/__init__.py: -------------------------------------------------------------------------------- 1 | #-*- coding: ISO-8859-1 -*- 2 | # pysqlite2/test/__init__.py: the package containing the test suite 3 | # 4 | # Copyright (C) 2004-2007 Gerhard H�ring 5 | # 6 | # This file is part of pysqlite. 7 | # 8 | # This software is provided 'as-is', without any express or implied 9 | # warranty. In no event will the authors be held liable for any damages 10 | # arising from the use of this software. 11 | # 12 | # Permission is granted to anyone to use this software for any purpose, 13 | # including commercial applications, and to alter it and redistribute it 14 | # freely, subject to the following restrictions: 15 | # 16 | # 1. The origin of this software must not be misrepresented; you must not 17 | # claim that you wrote the original software. If you use this software 18 | # in a product, an acknowledgment in the product documentation would be 19 | # appreciated but is not required. 20 | # 2. Altered source versions must be plainly marked as such, and must not be 21 | # misrepresented as being the original software. 22 | # 3. This notice may not be removed or altered from any source distribution. 23 | import sys 24 | import unittest 25 | 26 | if sys.version_info[0] < 3: 27 | from pysqlcipher3.test.python2 import suite 28 | else: 29 | from pysqlcipher3.test.python3 import suite 30 | 31 | 32 | def test(): 33 | runner = unittest.TextTestRunner() 34 | runner.run(suite()) -------------------------------------------------------------------------------- /lib/test/python2/__init__.py: -------------------------------------------------------------------------------- 1 | #-*- coding: ISO-8859-1 -*- 2 | # pysqlite2/test/__init__.py: the package containing the test suite 3 | # 4 | # Copyright (C) 2004-2007 Gerhard H�ring 5 | # 6 | # This file is part of pysqlite. 7 | # 8 | # This software is provided 'as-is', without any express or implied 9 | # warranty. In no event will the authors be held liable for any damages 10 | # arising from the use of this software. 11 | # 12 | # Permission is granted to anyone to use this software for any purpose, 13 | # including commercial applications, and to alter it and redistribute it 14 | # freely, subject to the following restrictions: 15 | # 16 | # 1. The origin of this software must not be misrepresented; you must not 17 | # claim that you wrote the original software. If you use this software 18 | # in a product, an acknowledgment in the product documentation would be 19 | # appreciated but is not required. 20 | # 2. Altered source versions must be plainly marked as such, and must not be 21 | # misrepresented as being the original software. 22 | # 3. This notice may not be removed or altered from any source distribution. 23 | import unittest 24 | 25 | from pysqlcipher3.test.python2 import (dbapi, dump, factory, hooks, regression, 26 | transactions, types, userfunctions, sqlcipher) 27 | 28 | 29 | def suite(): 30 | return unittest.TestSuite(tuple([ 31 | dbapi.suite(), 32 | dump.suite(), 33 | factory.suite(), 34 | hooks.suite(), 35 | regression.suite(), 36 | transactions.suite(), 37 | types.suite(), 38 | userfunctions.suite(), 39 | sqlcipher.suite() 40 | ])) -------------------------------------------------------------------------------- /lib/test/python2/dbapi.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/dbapi.py -------------------------------------------------------------------------------- /lib/test/python2/dump.py: -------------------------------------------------------------------------------- 1 | # Author: Paul Kippes 2 | 3 | import unittest 4 | from pysqlcipher3 import dbapi2 as sqlite 5 | 6 | class DumpTests(unittest.TestCase): 7 | def setUp(self): 8 | self.cx = sqlite.connect(":memory:") 9 | self.cu = self.cx.cursor() 10 | 11 | def tearDown(self): 12 | self.cx.close() 13 | 14 | def CheckTableDump(self): 15 | expected_sqls = [ 16 | "CREATE TABLE t1(id integer primary key, s1 text, " \ 17 | "t1_i1 integer not null, i2 integer, unique (s1), " \ 18 | "constraint t1_idx1 unique (i2));" 19 | , 20 | "INSERT INTO \"t1\" VALUES(1,'foo',10,20);" 21 | , 22 | "INSERT INTO \"t1\" VALUES(2,'foo2',30,30);" 23 | , 24 | "CREATE TABLE t2(id integer, t2_i1 integer, " \ 25 | "t2_i2 integer, primary key (id)," \ 26 | "foreign key(t2_i1) references t1(t1_i1));" 27 | , 28 | "CREATE TRIGGER trigger_1 update of t1_i1 on t1 " \ 29 | "begin " \ 30 | "update t2 set t2_i1 = new.t1_i1 where t2_i1 = old.t1_i1; " \ 31 | "end;" 32 | , 33 | "CREATE VIEW v1 as select * from t1 left join t2 " \ 34 | "using (id);" 35 | ] 36 | [self.cu.execute(s) for s in expected_sqls] 37 | i = self.cx.iterdump() 38 | actual_sqls = [s for s in i] 39 | expected_sqls = ['BEGIN TRANSACTION;'] + expected_sqls + \ 40 | ['COMMIT;'] 41 | [self.assertEqual(expected_sqls[i], actual_sqls[i]) 42 | for i in xrange(len(expected_sqls))] 43 | 44 | def suite(): 45 | return unittest.TestSuite(unittest.makeSuite(DumpTests, "Check")) 46 | 47 | def test(): 48 | runner = unittest.TextTestRunner() 49 | runner.run(suite()) 50 | 51 | if __name__ == "__main__": 52 | test() 53 | -------------------------------------------------------------------------------- /lib/test/python2/factory.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/factory.py -------------------------------------------------------------------------------- /lib/test/python2/hooks.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/hooks.py -------------------------------------------------------------------------------- /lib/test/python2/regression.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/regression.py -------------------------------------------------------------------------------- /lib/test/python2/sqlcipher.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import unittest 4 | import tempfile 5 | import pysqlcipher3.dbapi2 as sqlite 6 | 7 | 8 | class SqlCipherTests(unittest.TestCase): 9 | 10 | password = 'testing' 11 | 12 | def testCorrectPasswordEntered(self): 13 | """ Test fetching data after entering the correct password """ 14 | self.createDatabase() 15 | self.assertSuccessfulQuery(self.password) 16 | 17 | def testNoPasswordEntered(self): 18 | """ Test for database exception when entering no password """ 19 | self.createDatabase() 20 | self.assertDatabaseError(None) 21 | 22 | def testWrongPasswordEntered(self): 23 | """ Test for database exception when entering wrong password """ 24 | self.createDatabase() 25 | self.assertDatabaseError("Wrong password") 26 | 27 | def testChangePassword(self): 28 | """ Test for changing the database password """ 29 | new_password = "New password" 30 | self.createDatabase() 31 | self.assertSuccessfulQuery(self.password) 32 | self.changePassword(self.password, new_password) 33 | self.assertDatabaseError(self.password) 34 | self.assertSuccessfulQuery(new_password) 35 | 36 | def testAddPassword(self): 37 | """ Test for adding a password to a plaintext database """ 38 | self.createDatabase(encrypt=False) 39 | self.assertSuccessfulQuery(None) 40 | 41 | encrypted_db = os.path.join(self.temp_dir, 'encrypted.db') 42 | conn = sqlite.connect(self.db) 43 | conn.executescript("ATTACH DATABASE '" + encrypted_db + "'" + 44 | "AS encrypted KEY '" + self.password + "'") 45 | conn.executescript("SELECT sqlcipher_export('encrypted')") 46 | conn.executescript("DETACH DATABASE encrypted") 47 | conn.close() 48 | if os.path.exists(self.db): 49 | os.remove(self.db) 50 | os.rename(encrypted_db, self.db) 51 | self.assertDatabaseError(None) 52 | self.assertSuccessfulQuery(self.password) 53 | 54 | def setUp(self): 55 | self.temp_dir = tempfile.mkdtemp() 56 | self.db = os.path.join(self.temp_dir, 'test.db') 57 | 58 | def tearDown(self): 59 | if os.path.exists(self.temp_dir): 60 | shutil.rmtree(self.temp_dir) 61 | del self.temp_dir 62 | del self.db 63 | 64 | def createDatabase(self, encrypt=True): 65 | conn = sqlite.connect(self.db) 66 | if encrypt: 67 | self.setPassword(conn, self.password) 68 | conn.execute('create table tbl(col text)') 69 | conn.execute("insert into tbl values('data')") 70 | conn.commit() 71 | conn.close() 72 | 73 | def setPassword(self, conn, password, pragma="key"): 74 | if password is not None: 75 | conn.executescript("PRAGMA " + pragma + "='" + password + "'") 76 | 77 | def changePassword(self, old_password, new_password): 78 | conn = sqlite.connect(self.db) 79 | self.setPassword(conn, old_password) 80 | self.setPassword(conn, new_password, "rekey") 81 | conn.close() 82 | 83 | def queryData(self, conn): 84 | return conn.execute('select col from tbl').fetchone()[0] 85 | 86 | def assertSuccessfulQuery(self, password): 87 | conn = sqlite.connect(self.db) 88 | self.setPassword(conn, password) 89 | col_value = self.queryData(conn) 90 | self.assertEqual('data', col_value) 91 | conn.close() 92 | 93 | def assertDatabaseError(self, password): 94 | conn = sqlite.connect(self.db) 95 | self.setPassword(conn, password) 96 | try: 97 | col_value = self.queryData(conn) 98 | self.assertIsNone(col_value) 99 | except sqlite.DatabaseError as ex: 100 | self.assertIn('is not a database', str(ex)) 101 | finally: 102 | conn.close() 103 | 104 | 105 | def suite(): 106 | sqlcipher_suite = unittest.makeSuite(SqlCipherTests, "test") 107 | return unittest.TestSuite((sqlcipher_suite,)) 108 | 109 | 110 | def test(): 111 | runner = unittest.TextTestRunner() 112 | runner.run(suite()) 113 | 114 | if __name__ == "__main__": 115 | test() -------------------------------------------------------------------------------- /lib/test/python2/transactions.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/transactions.py -------------------------------------------------------------------------------- /lib/test/python2/types.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/types.py -------------------------------------------------------------------------------- /lib/test/python2/userfunctions.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python2/userfunctions.py -------------------------------------------------------------------------------- /lib/test/python3/__init__.py: -------------------------------------------------------------------------------- 1 | #-*- coding: ISO-8859-1 -*- 2 | # pysqlite2/test/__init__.py: the package containing the test suite 3 | # 4 | # Copyright (C) 2004-2007 Gerhard H�ring 5 | # 6 | # This file is part of pysqlite. 7 | # 8 | # This software is provided 'as-is', without any express or implied 9 | # warranty. In no event will the authors be held liable for any damages 10 | # arising from the use of this software. 11 | # 12 | # Permission is granted to anyone to use this software for any purpose, 13 | # including commercial applications, and to alter it and redistribute it 14 | # freely, subject to the following restrictions: 15 | # 16 | # 1. The origin of this software must not be misrepresented; you must not 17 | # claim that you wrote the original software. If you use this software 18 | # in a product, an acknowledgment in the product documentation would be 19 | # appreciated but is not required. 20 | # 2. Altered source versions must be plainly marked as such, and must not be 21 | # misrepresented as being the original software. 22 | # 3. This notice may not be removed or altered from any source distribution. 23 | import unittest 24 | 25 | from pysqlcipher3.test.python3 import (dbapi, dump, factory, hooks, regression, 26 | transactions, types, userfunctions, sqlcipher) 27 | 28 | 29 | def suite(): 30 | return unittest.TestSuite(tuple([ 31 | dbapi.suite(), 32 | dump.suite(), 33 | factory.suite(), 34 | hooks.suite(), 35 | regression.suite(), 36 | transactions.suite(), 37 | types.suite(), 38 | userfunctions.suite(), 39 | sqlcipher.suite() 40 | ])) -------------------------------------------------------------------------------- /lib/test/python3/dbapi.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/dbapi.py -------------------------------------------------------------------------------- /lib/test/python3/dump.py: -------------------------------------------------------------------------------- 1 | # Author: Paul Kippes 2 | 3 | import unittest 4 | import pysqlcipher3.dbapi2 as sqlite 5 | 6 | class DumpTests(unittest.TestCase): 7 | def setUp(self): 8 | self.cx = sqlite.connect(":memory:") 9 | self.cu = self.cx.cursor() 10 | 11 | def tearDown(self): 12 | self.cx.close() 13 | 14 | def CheckTableDump(self): 15 | expected_sqls = [ 16 | """CREATE TABLE "index"("index" blob);""" 17 | , 18 | """INSERT INTO "index" VALUES(X'01');""" 19 | , 20 | """CREATE TABLE "quoted""table"("quoted""field" text);""" 21 | , 22 | """INSERT INTO "quoted""table" VALUES('quoted''value');""" 23 | , 24 | "CREATE TABLE t1(id integer primary key, s1 text, " \ 25 | "t1_i1 integer not null, i2 integer, unique (s1), " \ 26 | "constraint t1_idx1 unique (i2));" 27 | , 28 | "INSERT INTO \"t1\" VALUES(1,'foo',10,20);" 29 | , 30 | "INSERT INTO \"t1\" VALUES(2,'foo2',30,30);" 31 | , 32 | "CREATE TABLE t2(id integer, t2_i1 integer, " \ 33 | "t2_i2 integer, primary key (id)," \ 34 | "foreign key(t2_i1) references t1(t1_i1));" 35 | , 36 | "CREATE TRIGGER trigger_1 update of t1_i1 on t1 " \ 37 | "begin " \ 38 | "update t2 set t2_i1 = new.t1_i1 where t2_i1 = old.t1_i1; " \ 39 | "end;" 40 | , 41 | "CREATE VIEW v1 as select * from t1 left join t2 " \ 42 | "using (id);" 43 | ] 44 | [self.cu.execute(s) for s in expected_sqls] 45 | i = self.cx.iterdump() 46 | actual_sqls = [s for s in i] 47 | expected_sqls = ['BEGIN TRANSACTION;'] + expected_sqls + \ 48 | ['COMMIT;'] 49 | [self.assertEqual(expected_sqls[i], actual_sqls[i]) 50 | for i in range(len(expected_sqls))] 51 | 52 | def CheckUnorderableRow(self): 53 | # iterdump() should be able to cope with unorderable row types (issue #15545) 54 | class UnorderableRow: 55 | def __init__(self, cursor, row): 56 | self.row = row 57 | def __getitem__(self, index): 58 | return self.row[index] 59 | self.cx.row_factory = UnorderableRow 60 | CREATE_ALPHA = """CREATE TABLE "alpha" ("one");""" 61 | CREATE_BETA = """CREATE TABLE "beta" ("two");""" 62 | expected = [ 63 | "BEGIN TRANSACTION;", 64 | CREATE_ALPHA, 65 | CREATE_BETA, 66 | "COMMIT;" 67 | ] 68 | self.cu.execute(CREATE_BETA) 69 | self.cu.execute(CREATE_ALPHA) 70 | got = list(self.cx.iterdump()) 71 | self.assertEqual(expected, got) 72 | 73 | def suite(): 74 | return unittest.TestSuite(unittest.makeSuite(DumpTests, "Check")) 75 | 76 | def test(): 77 | runner = unittest.TextTestRunner() 78 | runner.run(suite()) 79 | 80 | if __name__ == "__main__": 81 | test() 82 | -------------------------------------------------------------------------------- /lib/test/python3/factory.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/factory.py -------------------------------------------------------------------------------- /lib/test/python3/hooks.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/hooks.py -------------------------------------------------------------------------------- /lib/test/python3/regression.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/regression.py -------------------------------------------------------------------------------- /lib/test/python3/sqlcipher.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import tempfile 4 | import unittest 5 | import pysqlcipher3.dbapi2 as sqlite 6 | 7 | 8 | class SqlCipherTests(unittest.TestCase): 9 | 10 | password = 'testing' 11 | 12 | def testCorrectPasswordEntered(self): 13 | """ Test fetching data after entering the correct password """ 14 | self.createDatabase() 15 | self.assertSuccessfulQuery(self.password) 16 | 17 | def testNoPasswordEntered(self): 18 | """ Test for database exception when entering no password """ 19 | self.createDatabase() 20 | self.assertDatabaseError(None) 21 | 22 | def testWrongPasswordEntered(self): 23 | """ Test for database exception when entering wrong password """ 24 | self.createDatabase() 25 | self.assertDatabaseError("Wrong password") 26 | 27 | def testChangePassword(self): 28 | """ Test for changing the database password """ 29 | new_password = "New password" 30 | self.createDatabase() 31 | self.assertSuccessfulQuery(self.password) 32 | self.changePassword(self.password, new_password) 33 | self.assertDatabaseError(self.password) 34 | self.assertSuccessfulQuery(new_password) 35 | 36 | def testAddPassword(self): 37 | """ Test for adding a password to a plaintext database """ 38 | self.createDatabase(encrypt=False) 39 | self.assertSuccessfulQuery(None) 40 | 41 | encrypted_db = os.path.join(self.temp_dir, 'encrypted.db') 42 | conn = sqlite.connect(self.db) 43 | conn.executescript("ATTACH DATABASE '" + encrypted_db + "'" + 44 | "AS encrypted KEY '" + self.password + "'") 45 | conn.executescript("SELECT sqlcipher_export('encrypted')") 46 | conn.executescript("DETACH DATABASE encrypted") 47 | conn.close() 48 | if os.path.exists(self.db): 49 | os.remove(self.db) 50 | os.rename(encrypted_db, self.db) 51 | self.assertDatabaseError(None) 52 | self.assertSuccessfulQuery(self.password) 53 | 54 | def setUp(self): 55 | self.temp_dir = tempfile.mkdtemp() 56 | self.db = os.path.join(self.temp_dir, 'test.db') 57 | 58 | def tearDown(self): 59 | if os.path.exists(self.temp_dir): 60 | shutil.rmtree(self.temp_dir) 61 | del self.temp_dir 62 | del self.db 63 | 64 | def createDatabase(self, encrypt=True): 65 | conn = sqlite.connect(self.db) 66 | if encrypt: 67 | self.setPassword(conn, self.password) 68 | conn.execute('create table tbl(col text)') 69 | conn.execute("insert into tbl values('data')") 70 | conn.commit() 71 | conn.close() 72 | 73 | def setPassword(self, conn, password, pragma="key"): 74 | if password is not None: 75 | conn.executescript("PRAGMA " + pragma + "='" + password + "'") 76 | 77 | def changePassword(self, old_password, new_password): 78 | conn = sqlite.connect(self.db) 79 | self.setPassword(conn, old_password) 80 | self.setPassword(conn, new_password, "rekey") 81 | conn.close() 82 | 83 | def queryData(self, conn): 84 | return conn.execute('select col from tbl').fetchone()[0] 85 | 86 | def assertSuccessfulQuery(self, password): 87 | conn = sqlite.connect(self.db) 88 | self.setPassword(conn, password) 89 | col_value = self.queryData(conn) 90 | self.assertEqual('data', col_value) 91 | conn.close() 92 | 93 | def assertDatabaseError(self, password): 94 | conn = sqlite.connect(self.db) 95 | self.setPassword(conn, password) 96 | try: 97 | col_value = self.queryData(conn) 98 | self.assertIsNone(col_value) 99 | except sqlite.DatabaseError as ex: 100 | self.assertIn('is not a database', str(ex)) 101 | finally: 102 | conn.close() 103 | 104 | 105 | def suite(): 106 | sqlcipher_suite = unittest.makeSuite(SqlCipherTests, "test") 107 | return unittest.TestSuite((sqlcipher_suite,)) 108 | 109 | 110 | def test(): 111 | runner = unittest.TextTestRunner() 112 | runner.run(suite()) 113 | 114 | if __name__ == "__main__": 115 | test() -------------------------------------------------------------------------------- /lib/test/python3/transactions.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/transactions.py -------------------------------------------------------------------------------- /lib/test/python3/types.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/types.py -------------------------------------------------------------------------------- /lib/test/python3/userfunctions.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/lib/test/python3/userfunctions.py -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [build_ext] 2 | libraries=sqlcipher 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: ISO-8859-1 -*- 2 | # setup.py: the distutils script 3 | # 4 | # Copyright (C) 2015 David Riggleman 5 | # Copyright (C) 2013 Kali Kaneko (sqlcipher support) 6 | # Copyright (C) 2005-2010 Gerhard Häring 7 | # 8 | # This file is part of pysqlcipher. 9 | # 10 | # This software is provided 'as-is', without any express or implied 11 | # warranty. In no event will the authors be held liable for any damages 12 | # arising from the use of this software. 13 | # 14 | # Permission is granted to anyone to use this software for any purpose, 15 | # including commercial applications, and to alter it and redistribute it 16 | # freely, subject to the following restrictions: 17 | # 18 | # 1. The origin of this software must not be misrepresented; you must not 19 | # claim that you wrote the original software. If you use this software 20 | # in a product, an acknowledgment in the product documentation would be 21 | # appreciated but is not required. 22 | # 2. Altered source versions must be plainly marked as such, and must not be 23 | # misrepresented as being the original software. 24 | # 3. This notice may not be removed or altered from any source distribution. 25 | import os 26 | import setuptools 27 | import sys 28 | 29 | from distutils import log 30 | from distutils.command.build_ext import build_ext 31 | from setuptools import Extension 32 | 33 | # If you need to change anything, it should be enough to change setup.cfg. 34 | 35 | PACKAGE_NAME = "pysqlcipher3" 36 | VERSION = '1.2.1' 37 | LONG_DESCRIPTION = \ 38 | """Python interface to SQLCipher 39 | 40 | pysqlcipher3 is an interface to the SQLite 3.x embedded relational 41 | database engine. It is almost fully compliant with the Python database API 42 | version 2.0. At the same time, it also exposes the unique features of 43 | SQLCipher. Prior to installation, libsqlcipher must already be installed 44 | on your system, with the process dependent on your operating system.""" 45 | 46 | # define sqlite sources 47 | sources = [os.path.join("src", "python" + str(sys.version_info[0]), source) 48 | for source in ["module.c", "connection.c", "cursor.c", "cache.c", 49 | "microprotocols.c", "prepare_protocol.c", 50 | "statement.c", "util.c", "row.c"]] 51 | 52 | # define packages 53 | packages = [PACKAGE_NAME, PACKAGE_NAME + ".test"] 54 | 55 | if sys.version_info[0] < 3: 56 | packages.append(PACKAGE_NAME + ".test.python2") 57 | EXTENSION_MODULE_NAME = "._sqlite" 58 | else: 59 | packages.append(PACKAGE_NAME + ".test.python3") 60 | EXTENSION_MODULE_NAME = "._sqlite3" 61 | 62 | # Work around clang raising hard error for unused arguments 63 | if sys.platform == "darwin": 64 | os.environ['CFLAGS'] = "-Qunused-arguments" 65 | log.info("CFLAGS: " + os.environ['CFLAGS']) 66 | 67 | 68 | def quote_argument(arg): 69 | quote = '"' if sys.platform != 'win32' else '\\"' 70 | return quote + arg + quote 71 | 72 | define_macros = [('MODULE_NAME', quote_argument(PACKAGE_NAME + '.dbapi2'))] 73 | 74 | 75 | class SystemLibSQLCipherBuilder(build_ext): 76 | description = "Builds a C extension linking against libsqlcipher library" 77 | 78 | def build_extension(self, ext): 79 | log.info(self.description) 80 | build_ext.build_extension(self, ext) 81 | 82 | 83 | class AmalgationLibSQLCipherBuilder(build_ext): 84 | description = "Builds a C extension using a sqlcipher amalgamation" 85 | 86 | amalgamation_root = "amalgamation" 87 | amalgamation_header = os.path.join(amalgamation_root, 'sqlite3.h') 88 | amalgamation_source = os.path.join(amalgamation_root, 'sqlite3.c') 89 | 90 | amalgamation_message = \ 91 | """SQL Cipher amalgamation not found. Please download or build the 92 | amalgamation and make sure the following files are present in the 93 | amalgamation folder: sqlite3.h, sqlite3.c""" 94 | 95 | def check_amalgamation(self): 96 | if not os.path.exists(self.amalgamation_root): 97 | os.mkdir(self.amalgamation_root) 98 | 99 | header_exists = os.path.exists(self.amalgamation_header) 100 | source_exists = os.path.exists(self.amalgamation_source) 101 | if not header_exists or not source_exists: 102 | raise RuntimeError(self.amalgamation_message) 103 | 104 | def build_extension(self, ext): 105 | log.info(self.description) 106 | 107 | # it is responsibility of user to provide amalgamation 108 | self.check_amalgamation() 109 | 110 | # build with fulltext search enabled 111 | ext.define_macros.append(("SQLITE_ENABLE_FTS3", "1")) 112 | ext.define_macros.append(("SQLITE_ENABLE_RTREE", "1")) 113 | 114 | # SQLCipher options 115 | ext.define_macros.append(("SQLITE_ENABLE_LOAD_EXTENSION", "1")) 116 | ext.define_macros.append(("SQLITE_HAS_CODEC", "1")) 117 | ext.define_macros.append(("SQLITE_TEMP_STORE", "2")) 118 | 119 | ext.include_dirs.append(self.amalgamation_root) 120 | ext.sources.append(os.path.join(self.amalgamation_root, "sqlite3.c")) 121 | 122 | if sys.platform == "win32": 123 | # Try to locate openssl 124 | openssl_conf = os.environ.get('OPENSSL_CONF') 125 | if not openssl_conf: 126 | error_message = 'Fatal error: OpenSSL could not be detected!' 127 | raise RuntimeError(error_message) 128 | 129 | openssl = os.path.dirname(os.path.dirname(openssl_conf)) 130 | openssl_lib_path = os.path.join(openssl, "lib") 131 | 132 | # Configure the compiler 133 | ext.include_dirs.append(os.path.join(openssl, "include")) 134 | ext.define_macros.append(("inline", "__inline")) 135 | 136 | # Configure the linker 137 | ext.extra_link_args.append("libeay32.lib") 138 | ext.extra_link_args.append('/LIBPATH:' + openssl_lib_path) 139 | else: 140 | ext.extra_link_args.append("-lcrypto") 141 | 142 | build_ext.build_extension(self, ext) 143 | 144 | def __setattr__(self, k, v): 145 | # Make sure we don't link against the SQLite 146 | # library, no matter what setup.cfg says 147 | if k == "libraries": 148 | v = None 149 | self.__dict__[k] = v 150 | 151 | 152 | def get_setup_args(): 153 | return dict( 154 | name=PACKAGE_NAME, 155 | version=VERSION, 156 | python_requires=">=3.3", 157 | description="DB-API 2.0 interface for SQLCIPHER 3.x", 158 | long_description=LONG_DESCRIPTION, 159 | author="David Riggleman", 160 | author_email="davidriggleman@gmail.com", 161 | license="zlib/libpng", 162 | platforms="ALL", 163 | url="https://github.com/rigglemania/pysqlcipher3", 164 | package_dir={PACKAGE_NAME: "lib"}, 165 | packages=packages, 166 | ext_modules=[Extension( 167 | name=PACKAGE_NAME + EXTENSION_MODULE_NAME, 168 | sources=sources, 169 | define_macros=define_macros) 170 | ], 171 | classifiers=[ 172 | "Development Status :: 4 - Beta", 173 | "Intended Audience :: Developers", 174 | "License :: OSI Approved :: zlib/libpng License", 175 | "Operating System :: MacOS :: MacOS X", 176 | "Operating System :: Microsoft :: Windows", 177 | "Operating System :: POSIX", 178 | "Programming Language :: C", 179 | "Programming Language :: Python", 180 | "Topic :: Database :: Database Engines/Servers", 181 | "Topic :: Software Development :: Libraries :: Python Modules"], 182 | cmdclass={ 183 | "build_amalgamation": AmalgationLibSQLCipherBuilder, 184 | "build_ext": SystemLibSQLCipherBuilder 185 | } 186 | ) 187 | 188 | 189 | def main(): 190 | try: 191 | setuptools.setup(**get_setup_args()) 192 | except BaseException as ex: 193 | log.info(str(ex)) 194 | 195 | if __name__ == "__main__": 196 | main() 197 | -------------------------------------------------------------------------------- /src/python2/backup.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/backup.h -------------------------------------------------------------------------------- /src/python2/cache.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/cache.c -------------------------------------------------------------------------------- /src/python2/cache.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/cache.h -------------------------------------------------------------------------------- /src/python2/connection.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/connection.c -------------------------------------------------------------------------------- /src/python2/connection.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/connection.h -------------------------------------------------------------------------------- /src/python2/cursor.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/cursor.c -------------------------------------------------------------------------------- /src/python2/cursor.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/cursor.h -------------------------------------------------------------------------------- /src/python2/microprotocols.c: -------------------------------------------------------------------------------- 1 | /* microprotocols.c - minimalist and non-validating protocols implementation 2 | * 3 | * Copyright (C) 2003-2004 Federico Di Gregorio 4 | * 5 | * This file is part of psycopg and was adapted for pysqlite. Federico Di 6 | * Gregorio gave the permission to use it within pysqlite under the following 7 | * license: 8 | * 9 | * This software is provided 'as-is', without any express or implied 10 | * warranty. In no event will the authors be held liable for any damages 11 | * arising from the use of this software. 12 | * 13 | * Permission is granted to anyone to use this software for any purpose, 14 | * including commercial applications, and to alter it and redistribute it 15 | * freely, subject to the following restrictions: 16 | * 17 | * 1. The origin of this software must not be misrepresented; you must not 18 | * claim that you wrote the original software. If you use this software 19 | * in a product, an acknowledgment in the product documentation would be 20 | * appreciated but is not required. 21 | * 2. Altered source versions must be plainly marked as such, and must not be 22 | * misrepresented as being the original software. 23 | * 3. This notice may not be removed or altered from any source distribution. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "cursor.h" 30 | #include "microprotocols.h" 31 | #include "prepare_protocol.h" 32 | 33 | 34 | /** the adapters registry **/ 35 | 36 | PyObject *psyco_adapters; 37 | 38 | /* pysqlite_microprotocols_init - initialize the adapters dictionary */ 39 | 40 | int 41 | pysqlite_microprotocols_init(PyObject *dict) 42 | { 43 | /* create adapters dictionary and put it in module namespace */ 44 | if ((psyco_adapters = PyDict_New()) == NULL) { 45 | return -1; 46 | } 47 | 48 | return PyDict_SetItemString(dict, "adapters", psyco_adapters); 49 | } 50 | 51 | 52 | /* pysqlite_microprotocols_add - add a reverse type-caster to the dictionary */ 53 | 54 | int 55 | pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) 56 | { 57 | PyObject* key; 58 | int rc; 59 | 60 | if (proto == NULL) proto = (PyObject*)&pysqlite_PrepareProtocolType; 61 | 62 | key = Py_BuildValue("(OO)", (PyObject*)type, proto); 63 | if (!key) { 64 | return -1; 65 | } 66 | 67 | rc = PyDict_SetItem(psyco_adapters, key, cast); 68 | Py_DECREF(key); 69 | 70 | return rc; 71 | } 72 | 73 | /* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */ 74 | 75 | PyObject * 76 | pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) 77 | { 78 | PyObject *adapter, *key; 79 | 80 | /* we don't check for exact type conformance as specified in PEP 246 81 | because the pysqlite_PrepareProtocolType type is abstract and there is no 82 | way to get a quotable object to be its instance */ 83 | 84 | /* look for an adapter in the registry */ 85 | key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto); 86 | if (!key) { 87 | return NULL; 88 | } 89 | adapter = PyDict_GetItem(psyco_adapters, key); 90 | Py_DECREF(key); 91 | if (adapter) { 92 | PyObject *adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL); 93 | return adapted; 94 | } 95 | 96 | /* try to have the protocol adapt this object*/ 97 | if (PyObject_HasAttrString(proto, "__adapt__")) { 98 | PyObject *adapted = PyObject_CallMethod(proto, "__adapt__", "O", obj); 99 | if (adapted) { 100 | if (adapted != Py_None) { 101 | return adapted; 102 | } else { 103 | Py_DECREF(adapted); 104 | } 105 | } 106 | 107 | if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) 108 | return NULL; 109 | } 110 | 111 | /* and finally try to have the object adapt itself */ 112 | if (PyObject_HasAttrString(obj, "__conform__")) { 113 | PyObject *adapted = PyObject_CallMethod(obj, "__conform__","O", proto); 114 | if (adapted) { 115 | if (adapted != Py_None) { 116 | return adapted; 117 | } else { 118 | Py_DECREF(adapted); 119 | } 120 | } 121 | 122 | if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) { 123 | return NULL; 124 | } 125 | } 126 | 127 | /* else set the right exception and return NULL */ 128 | PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); 129 | return NULL; 130 | } 131 | 132 | /** module-level functions **/ 133 | 134 | PyObject * 135 | pysqlite_adapt(pysqlite_Cursor *self, PyObject *args) 136 | { 137 | PyObject *obj, *alt = NULL; 138 | PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType; 139 | 140 | if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL; 141 | return pysqlite_microprotocols_adapt(obj, proto, alt); 142 | } 143 | -------------------------------------------------------------------------------- /src/python2/microprotocols.h: -------------------------------------------------------------------------------- 1 | /* microprotocols.c - definitions for minimalist and non-validating protocols 2 | * 3 | * Copyright (C) 2003-2004 Federico Di Gregorio 4 | * 5 | * This file is part of psycopg and was adapted for pysqlite. Federico Di 6 | * Gregorio gave the permission to use it within pysqlite under the following 7 | * license: 8 | * 9 | * This software is provided 'as-is', without any express or implied 10 | * warranty. In no event will the authors be held liable for any damages 11 | * arising from the use of this software. 12 | * 13 | * Permission is granted to anyone to use this software for any purpose, 14 | * including commercial applications, and to alter it and redistribute it 15 | * freely, subject to the following restrictions: 16 | * 17 | * 1. The origin of this software must not be misrepresented; you must not 18 | * claim that you wrote the original software. If you use this software 19 | * in a product, an acknowledgment in the product documentation would be 20 | * appreciated but is not required. 21 | * 2. Altered source versions must be plainly marked as such, and must not be 22 | * misrepresented as being the original software. 23 | * 3. This notice may not be removed or altered from any source distribution. 24 | */ 25 | 26 | #ifndef PSYCOPG_MICROPROTOCOLS_H 27 | #define PSYCOPG_MICROPROTOCOLS_H 1 28 | 29 | #include 30 | 31 | /** adapters registry **/ 32 | 33 | extern PyObject *psyco_adapters; 34 | 35 | /** the names of the three mandatory methods **/ 36 | 37 | #define MICROPROTOCOLS_GETQUOTED_NAME "getquoted" 38 | #define MICROPROTOCOLS_GETSTRING_NAME "getstring" 39 | #define MICROPROTOCOLS_GETBINARY_NAME "getbinary" 40 | 41 | /** exported functions **/ 42 | 43 | /* used by module.c to init the microprotocols system */ 44 | extern int pysqlite_microprotocols_init(PyObject *dict); 45 | extern int pysqlite_microprotocols_add( 46 | PyTypeObject *type, PyObject *proto, PyObject *cast); 47 | extern PyObject *pysqlite_microprotocols_adapt( 48 | PyObject *obj, PyObject *proto, PyObject *alt); 49 | 50 | extern PyObject * 51 | pysqlite_adapt(pysqlite_Cursor* self, PyObject *args); 52 | #define pysqlite_adapt_doc \ 53 | "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard." 54 | 55 | #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ 56 | -------------------------------------------------------------------------------- /src/python2/module.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/module.c -------------------------------------------------------------------------------- /src/python2/module.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/module.h -------------------------------------------------------------------------------- /src/python2/prepare_protocol.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/prepare_protocol.c -------------------------------------------------------------------------------- /src/python2/prepare_protocol.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/prepare_protocol.h -------------------------------------------------------------------------------- /src/python2/row.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/row.c -------------------------------------------------------------------------------- /src/python2/row.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/row.h -------------------------------------------------------------------------------- /src/python2/sqlitecompat.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/sqlitecompat.h -------------------------------------------------------------------------------- /src/python2/statement.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/statement.c -------------------------------------------------------------------------------- /src/python2/statement.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/statement.h -------------------------------------------------------------------------------- /src/python2/util.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/util.c -------------------------------------------------------------------------------- /src/python2/util.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rigglemania/pysqlcipher3/e10b09c569ea60d4a9a5289d9d67112eb0f2c95a/src/python2/util.h -------------------------------------------------------------------------------- /src/python3/cache.c: -------------------------------------------------------------------------------- 1 | /* cache .c - a LRU cache 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "cache.h" 25 | #include 26 | 27 | /* only used internally */ 28 | pysqlite_Node* pysqlite_new_node(PyObject* key, PyObject* data) 29 | { 30 | pysqlite_Node* node; 31 | 32 | node = (pysqlite_Node*) (pysqlite_NodeType.tp_alloc(&pysqlite_NodeType, 0)); 33 | if (!node) { 34 | return NULL; 35 | } 36 | 37 | Py_INCREF(key); 38 | node->key = key; 39 | 40 | Py_INCREF(data); 41 | node->data = data; 42 | 43 | node->prev = NULL; 44 | node->next = NULL; 45 | 46 | return node; 47 | } 48 | 49 | void pysqlite_node_dealloc(pysqlite_Node* self) 50 | { 51 | Py_DECREF(self->key); 52 | Py_DECREF(self->data); 53 | 54 | Py_TYPE(self)->tp_free((PyObject*)self); 55 | } 56 | 57 | int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs) 58 | { 59 | PyObject* factory; 60 | int size = 10; 61 | 62 | self->factory = NULL; 63 | 64 | if (!PyArg_ParseTuple(args, "O|i", &factory, &size)) { 65 | return -1; 66 | } 67 | 68 | /* minimum cache size is 5 entries */ 69 | if (size < 5) { 70 | size = 5; 71 | } 72 | self->size = size; 73 | self->first = NULL; 74 | self->last = NULL; 75 | 76 | self->mapping = PyDict_New(); 77 | if (!self->mapping) { 78 | return -1; 79 | } 80 | 81 | Py_INCREF(factory); 82 | self->factory = factory; 83 | 84 | self->decref_factory = 1; 85 | 86 | return 0; 87 | } 88 | 89 | void pysqlite_cache_dealloc(pysqlite_Cache* self) 90 | { 91 | pysqlite_Node* node; 92 | pysqlite_Node* delete_node; 93 | 94 | if (!self->factory) { 95 | /* constructor failed, just get out of here */ 96 | return; 97 | } 98 | 99 | /* iterate over all nodes and deallocate them */ 100 | node = self->first; 101 | while (node) { 102 | delete_node = node; 103 | node = node->next; 104 | Py_DECREF(delete_node); 105 | } 106 | 107 | if (self->decref_factory) { 108 | Py_DECREF(self->factory); 109 | } 110 | Py_DECREF(self->mapping); 111 | 112 | Py_TYPE(self)->tp_free((PyObject*)self); 113 | } 114 | 115 | PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args) 116 | { 117 | PyObject* key = args; 118 | pysqlite_Node* node; 119 | pysqlite_Node* ptr; 120 | PyObject* data; 121 | 122 | node = (pysqlite_Node*)PyDict_GetItem(self->mapping, key); 123 | if (node) { 124 | /* an entry for this key already exists in the cache */ 125 | 126 | /* increase usage counter of the node found */ 127 | if (node->count < LONG_MAX) { 128 | node->count++; 129 | } 130 | 131 | /* if necessary, reorder entries in the cache by swapping positions */ 132 | if (node->prev && node->count > node->prev->count) { 133 | ptr = node->prev; 134 | 135 | while (ptr->prev && node->count > ptr->prev->count) { 136 | ptr = ptr->prev; 137 | } 138 | 139 | if (node->next) { 140 | node->next->prev = node->prev; 141 | } else { 142 | self->last = node->prev; 143 | } 144 | if (node->prev) { 145 | node->prev->next = node->next; 146 | } 147 | if (ptr->prev) { 148 | ptr->prev->next = node; 149 | } else { 150 | self->first = node; 151 | } 152 | 153 | node->next = ptr; 154 | node->prev = ptr->prev; 155 | if (!node->prev) { 156 | self->first = node; 157 | } 158 | ptr->prev = node; 159 | } 160 | } else { 161 | /* There is no entry for this key in the cache, yet. We'll insert a new 162 | * entry in the cache, and make space if necessary by throwing the 163 | * least used item out of the cache. */ 164 | 165 | if (PyDict_Size(self->mapping) == self->size) { 166 | if (self->last) { 167 | node = self->last; 168 | 169 | if (PyDict_DelItem(self->mapping, self->last->key) != 0) { 170 | return NULL; 171 | } 172 | 173 | if (node->prev) { 174 | node->prev->next = NULL; 175 | } 176 | self->last = node->prev; 177 | node->prev = NULL; 178 | 179 | Py_DECREF(node); 180 | } 181 | } 182 | 183 | data = PyObject_CallFunction(self->factory, "O", key); 184 | 185 | if (!data) { 186 | return NULL; 187 | } 188 | 189 | node = pysqlite_new_node(key, data); 190 | if (!node) { 191 | return NULL; 192 | } 193 | node->prev = self->last; 194 | 195 | Py_DECREF(data); 196 | 197 | if (PyDict_SetItem(self->mapping, key, (PyObject*)node) != 0) { 198 | Py_DECREF(node); 199 | return NULL; 200 | } 201 | 202 | if (self->last) { 203 | self->last->next = node; 204 | } else { 205 | self->first = node; 206 | } 207 | self->last = node; 208 | } 209 | 210 | Py_INCREF(node->data); 211 | return node->data; 212 | } 213 | 214 | PyObject* pysqlite_cache_display(pysqlite_Cache* self, PyObject* args) 215 | { 216 | pysqlite_Node* ptr; 217 | PyObject* prevkey; 218 | PyObject* nextkey; 219 | PyObject* display_str; 220 | 221 | ptr = self->first; 222 | 223 | while (ptr) { 224 | if (ptr->prev) { 225 | prevkey = ptr->prev->key; 226 | } else { 227 | prevkey = Py_None; 228 | } 229 | 230 | if (ptr->next) { 231 | nextkey = ptr->next->key; 232 | } else { 233 | nextkey = Py_None; 234 | } 235 | 236 | display_str = PyUnicode_FromFormat("%S <- %S -> %S\n", 237 | prevkey, ptr->key, nextkey); 238 | if (!display_str) { 239 | return NULL; 240 | } 241 | PyObject_Print(display_str, stdout, Py_PRINT_RAW); 242 | Py_DECREF(display_str); 243 | 244 | ptr = ptr->next; 245 | } 246 | 247 | Py_INCREF(Py_None); 248 | return Py_None; 249 | } 250 | 251 | static PyMethodDef cache_methods[] = { 252 | {"get", (PyCFunction)pysqlite_cache_get, METH_O, 253 | PyDoc_STR("Gets an entry from the cache or calls the factory function to produce one.")}, 254 | {"display", (PyCFunction)pysqlite_cache_display, METH_NOARGS, 255 | PyDoc_STR("For debugging only.")}, 256 | {NULL, NULL} 257 | }; 258 | 259 | PyTypeObject pysqlite_NodeType = { 260 | PyVarObject_HEAD_INIT(NULL, 0) 261 | MODULE_NAME "Node", /* tp_name */ 262 | sizeof(pysqlite_Node), /* tp_basicsize */ 263 | 0, /* tp_itemsize */ 264 | (destructor)pysqlite_node_dealloc, /* tp_dealloc */ 265 | 0, /* tp_print */ 266 | 0, /* tp_getattr */ 267 | 0, /* tp_setattr */ 268 | 0, /* tp_reserved */ 269 | 0, /* tp_repr */ 270 | 0, /* tp_as_number */ 271 | 0, /* tp_as_sequence */ 272 | 0, /* tp_as_mapping */ 273 | 0, /* tp_hash */ 274 | 0, /* tp_call */ 275 | 0, /* tp_str */ 276 | 0, /* tp_getattro */ 277 | 0, /* tp_setattro */ 278 | 0, /* tp_as_buffer */ 279 | Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 280 | 0, /* tp_doc */ 281 | 0, /* tp_traverse */ 282 | 0, /* tp_clear */ 283 | 0, /* tp_richcompare */ 284 | 0, /* tp_weaklistoffset */ 285 | 0, /* tp_iter */ 286 | 0, /* tp_iternext */ 287 | 0, /* tp_methods */ 288 | 0, /* tp_members */ 289 | 0, /* tp_getset */ 290 | 0, /* tp_base */ 291 | 0, /* tp_dict */ 292 | 0, /* tp_descr_get */ 293 | 0, /* tp_descr_set */ 294 | 0, /* tp_dictoffset */ 295 | (initproc)0, /* tp_init */ 296 | 0, /* tp_alloc */ 297 | 0, /* tp_new */ 298 | 0 /* tp_free */ 299 | }; 300 | 301 | PyTypeObject pysqlite_CacheType = { 302 | PyVarObject_HEAD_INIT(NULL, 0) 303 | MODULE_NAME ".Cache", /* tp_name */ 304 | sizeof(pysqlite_Cache), /* tp_basicsize */ 305 | 0, /* tp_itemsize */ 306 | (destructor)pysqlite_cache_dealloc, /* tp_dealloc */ 307 | 0, /* tp_print */ 308 | 0, /* tp_getattr */ 309 | 0, /* tp_setattr */ 310 | 0, /* tp_reserved */ 311 | 0, /* tp_repr */ 312 | 0, /* tp_as_number */ 313 | 0, /* tp_as_sequence */ 314 | 0, /* tp_as_mapping */ 315 | 0, /* tp_hash */ 316 | 0, /* tp_call */ 317 | 0, /* tp_str */ 318 | 0, /* tp_getattro */ 319 | 0, /* tp_setattro */ 320 | 0, /* tp_as_buffer */ 321 | Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 322 | 0, /* tp_doc */ 323 | 0, /* tp_traverse */ 324 | 0, /* tp_clear */ 325 | 0, /* tp_richcompare */ 326 | 0, /* tp_weaklistoffset */ 327 | 0, /* tp_iter */ 328 | 0, /* tp_iternext */ 329 | cache_methods, /* tp_methods */ 330 | 0, /* tp_members */ 331 | 0, /* tp_getset */ 332 | 0, /* tp_base */ 333 | 0, /* tp_dict */ 334 | 0, /* tp_descr_get */ 335 | 0, /* tp_descr_set */ 336 | 0, /* tp_dictoffset */ 337 | (initproc)pysqlite_cache_init, /* tp_init */ 338 | 0, /* tp_alloc */ 339 | 0, /* tp_new */ 340 | 0 /* tp_free */ 341 | }; 342 | 343 | extern int pysqlite_cache_setup_types(void) 344 | { 345 | int rc; 346 | 347 | pysqlite_NodeType.tp_new = PyType_GenericNew; 348 | pysqlite_CacheType.tp_new = PyType_GenericNew; 349 | 350 | rc = PyType_Ready(&pysqlite_NodeType); 351 | if (rc < 0) { 352 | return rc; 353 | } 354 | 355 | rc = PyType_Ready(&pysqlite_CacheType); 356 | return rc; 357 | } 358 | -------------------------------------------------------------------------------- /src/python3/cache.h: -------------------------------------------------------------------------------- 1 | /* cache.h - definitions for the LRU cache 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_CACHE_H 25 | #define PYSQLITE_CACHE_H 26 | #include "Python.h" 27 | 28 | /* The LRU cache is implemented as a combination of a doubly-linked with a 29 | * dictionary. The list items are of type 'Node' and the dictionary has the 30 | * nodes as values. */ 31 | 32 | typedef struct _pysqlite_Node 33 | { 34 | PyObject_HEAD 35 | PyObject* key; 36 | PyObject* data; 37 | long count; 38 | struct _pysqlite_Node* prev; 39 | struct _pysqlite_Node* next; 40 | } pysqlite_Node; 41 | 42 | typedef struct 43 | { 44 | PyObject_HEAD 45 | int size; 46 | 47 | /* a dictionary mapping keys to Node entries */ 48 | PyObject* mapping; 49 | 50 | /* the factory callable */ 51 | PyObject* factory; 52 | 53 | pysqlite_Node* first; 54 | pysqlite_Node* last; 55 | 56 | /* if set, decrement the factory function when the Cache is deallocated. 57 | * this is almost always desirable, but not in the pysqlite context */ 58 | int decref_factory; 59 | } pysqlite_Cache; 60 | 61 | extern PyTypeObject pysqlite_NodeType; 62 | extern PyTypeObject pysqlite_CacheType; 63 | 64 | int pysqlite_node_init(pysqlite_Node* self, PyObject* args, PyObject* kwargs); 65 | void pysqlite_node_dealloc(pysqlite_Node* self); 66 | 67 | int pysqlite_cache_init(pysqlite_Cache* self, PyObject* args, PyObject* kwargs); 68 | void pysqlite_cache_dealloc(pysqlite_Cache* self); 69 | PyObject* pysqlite_cache_get(pysqlite_Cache* self, PyObject* args); 70 | 71 | int pysqlite_cache_setup_types(void); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /src/python3/connection.h: -------------------------------------------------------------------------------- 1 | /* connection.h - definitions for the connection type 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_CONNECTION_H 25 | #define PYSQLITE_CONNECTION_H 26 | #include "Python.h" 27 | #include "pythread.h" 28 | #include "structmember.h" 29 | 30 | #include "cache.h" 31 | #include "module.h" 32 | 33 | #include "sqlcipher/sqlite3.h" 34 | 35 | typedef struct 36 | { 37 | PyObject_HEAD 38 | sqlite3* db; 39 | 40 | /* 1 if we are currently within a transaction, i. e. if a BEGIN has been 41 | * issued */ 42 | char inTransaction; 43 | 44 | /* the type detection mode. Only 0, PARSE_DECLTYPES, PARSE_COLNAMES or a 45 | * bitwise combination thereof makes sense */ 46 | int detect_types; 47 | 48 | /* the timeout value in seconds for database locks */ 49 | double timeout; 50 | 51 | /* for internal use in the timeout handler: when did the timeout handler 52 | * first get called with count=0? */ 53 | double timeout_started; 54 | 55 | /* None for autocommit, otherwise a PyString with the isolation level */ 56 | PyObject* isolation_level; 57 | 58 | /* NULL for autocommit, otherwise a string with the BEGIN statement; will be 59 | * freed in connection destructor */ 60 | char* begin_statement; 61 | 62 | /* 1 if a check should be performed for each API call if the connection is 63 | * used from the same thread it was created in */ 64 | int check_same_thread; 65 | 66 | int initialized; 67 | 68 | /* thread identification of the thread the connection was created in */ 69 | long thread_ident; 70 | 71 | pysqlite_Cache* statement_cache; 72 | 73 | /* Lists of weak references to statements and cursors used within this connection */ 74 | PyObject* statements; 75 | PyObject* cursors; 76 | 77 | /* Counters for how many statements/cursors were created in the connection. May be 78 | * reset to 0 at certain intervals */ 79 | int created_statements; 80 | int created_cursors; 81 | 82 | PyObject* row_factory; 83 | 84 | /* Determines how bytestrings from SQLite are converted to Python objects: 85 | * - PyUnicode_Type: Python Unicode objects are constructed from UTF-8 bytestrings 86 | * - PyBytes_Type: The bytestrings are returned as-is. 87 | * - Any custom callable: Any object returned from the callable called with the bytestring 88 | * as single parameter. 89 | */ 90 | PyObject* text_factory; 91 | 92 | /* remember references to functions/classes used in 93 | * create_function/create/aggregate, use these as dictionary keys, so we 94 | * can keep the total system refcount constant by clearing that dictionary 95 | * in connection_dealloc */ 96 | PyObject* function_pinboard; 97 | 98 | /* a dictionary of registered collation name => collation callable mappings */ 99 | PyObject* collations; 100 | 101 | /* Exception objects */ 102 | PyObject* Warning; 103 | PyObject* Error; 104 | PyObject* InterfaceError; 105 | PyObject* DatabaseError; 106 | PyObject* DataError; 107 | PyObject* OperationalError; 108 | PyObject* IntegrityError; 109 | PyObject* InternalError; 110 | PyObject* ProgrammingError; 111 | PyObject* NotSupportedError; 112 | } pysqlite_Connection; 113 | 114 | extern PyTypeObject pysqlite_ConnectionType; 115 | 116 | PyObject* pysqlite_connection_alloc(PyTypeObject* type, int aware); 117 | void pysqlite_connection_dealloc(pysqlite_Connection* self); 118 | PyObject* pysqlite_connection_cursor(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); 119 | PyObject* pysqlite_connection_close(pysqlite_Connection* self, PyObject* args); 120 | PyObject* _pysqlite_connection_begin(pysqlite_Connection* self); 121 | PyObject* pysqlite_connection_commit(pysqlite_Connection* self, PyObject* args); 122 | PyObject* pysqlite_connection_rollback(pysqlite_Connection* self, PyObject* args); 123 | PyObject* pysqlite_connection_new(PyTypeObject* type, PyObject* args, PyObject* kw); 124 | int pysqlite_connection_init(pysqlite_Connection* self, PyObject* args, PyObject* kwargs); 125 | 126 | int pysqlite_connection_register_cursor(pysqlite_Connection* connection, PyObject* cursor); 127 | int pysqlite_check_thread(pysqlite_Connection* self); 128 | int pysqlite_check_connection(pysqlite_Connection* con); 129 | 130 | int pysqlite_connection_setup_types(void); 131 | 132 | #endif 133 | -------------------------------------------------------------------------------- /src/python3/cursor.c: -------------------------------------------------------------------------------- 1 | /* cursor.c - the cursor type 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "cursor.h" 25 | #include "module.h" 26 | #include "util.h" 27 | 28 | PyObject* pysqlite_cursor_iternext(pysqlite_Cursor* self); 29 | 30 | static char* errmsg_fetch_across_rollback = "Cursor needed to be reset because of commit/rollback and can no longer be fetched from."; 31 | 32 | static pysqlite_StatementKind detect_statement_type(const char* statement) 33 | { 34 | char buf[20]; 35 | const char* src; 36 | char* dst; 37 | 38 | src = statement; 39 | /* skip over whitepace */ 40 | while (*src == '\r' || *src == '\n' || *src == ' ' || *src == '\t') { 41 | src++; 42 | } 43 | 44 | if (*src == 0) 45 | return STATEMENT_INVALID; 46 | 47 | dst = buf; 48 | *dst = 0; 49 | while (Py_ISALPHA(*src) && dst - buf < sizeof(buf) - 2) { 50 | *dst++ = Py_TOLOWER(*src++); 51 | } 52 | 53 | *dst = 0; 54 | 55 | if (!strcmp(buf, "select")) { 56 | return STATEMENT_SELECT; 57 | } else if (!strcmp(buf, "insert")) { 58 | return STATEMENT_INSERT; 59 | } else if (!strcmp(buf, "update")) { 60 | return STATEMENT_UPDATE; 61 | } else if (!strcmp(buf, "delete")) { 62 | return STATEMENT_DELETE; 63 | } else if (!strcmp(buf, "replace")) { 64 | return STATEMENT_REPLACE; 65 | } else { 66 | return STATEMENT_OTHER; 67 | } 68 | } 69 | 70 | static int pysqlite_cursor_init(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) 71 | { 72 | pysqlite_Connection* connection; 73 | 74 | if (!PyArg_ParseTuple(args, "O!", &pysqlite_ConnectionType, &connection)) 75 | { 76 | return -1; 77 | } 78 | 79 | Py_INCREF(connection); 80 | self->connection = connection; 81 | self->statement = NULL; 82 | self->next_row = NULL; 83 | self->in_weakreflist = NULL; 84 | 85 | self->row_cast_map = PyList_New(0); 86 | if (!self->row_cast_map) { 87 | return -1; 88 | } 89 | 90 | Py_INCREF(Py_None); 91 | self->description = Py_None; 92 | 93 | Py_INCREF(Py_None); 94 | self->lastrowid= Py_None; 95 | 96 | self->arraysize = 1; 97 | self->closed = 0; 98 | self->reset = 0; 99 | 100 | self->rowcount = -1L; 101 | 102 | Py_INCREF(Py_None); 103 | self->row_factory = Py_None; 104 | 105 | if (!pysqlite_check_thread(self->connection)) { 106 | return -1; 107 | } 108 | 109 | if (!pysqlite_connection_register_cursor(connection, (PyObject*)self)) { 110 | return -1; 111 | } 112 | 113 | self->initialized = 1; 114 | 115 | return 0; 116 | } 117 | 118 | static void pysqlite_cursor_dealloc(pysqlite_Cursor* self) 119 | { 120 | /* Reset the statement if the user has not closed the cursor */ 121 | if (self->statement) { 122 | pysqlite_statement_reset(self->statement); 123 | Py_DECREF(self->statement); 124 | } 125 | 126 | Py_XDECREF(self->connection); 127 | Py_XDECREF(self->row_cast_map); 128 | Py_XDECREF(self->description); 129 | Py_XDECREF(self->lastrowid); 130 | Py_XDECREF(self->row_factory); 131 | Py_XDECREF(self->next_row); 132 | 133 | if (self->in_weakreflist != NULL) { 134 | PyObject_ClearWeakRefs((PyObject*)self); 135 | } 136 | 137 | Py_TYPE(self)->tp_free((PyObject*)self); 138 | } 139 | 140 | PyObject* _pysqlite_get_converter(PyObject* key) 141 | { 142 | PyObject* upcase_key; 143 | PyObject* retval; 144 | _Py_IDENTIFIER(upper); 145 | 146 | upcase_key = _PyObject_CallMethodId(key, &PyId_upper, ""); 147 | if (!upcase_key) { 148 | return NULL; 149 | } 150 | 151 | retval = PyDict_GetItem(converters, upcase_key); 152 | Py_DECREF(upcase_key); 153 | 154 | return retval; 155 | } 156 | 157 | int pysqlite_build_row_cast_map(pysqlite_Cursor* self) 158 | { 159 | int i; 160 | const char* type_start = (const char*)-1; 161 | const char* pos; 162 | 163 | const char* colname; 164 | const char* decltype; 165 | PyObject* py_decltype; 166 | PyObject* converter; 167 | PyObject* key; 168 | 169 | if (!self->connection->detect_types) { 170 | return 0; 171 | } 172 | 173 | Py_XDECREF(self->row_cast_map); 174 | self->row_cast_map = PyList_New(0); 175 | 176 | for (i = 0; i < sqlite3_column_count(self->statement->st); i++) { 177 | converter = NULL; 178 | 179 | if (self->connection->detect_types & PARSE_COLNAMES) { 180 | colname = sqlite3_column_name(self->statement->st, i); 181 | if (colname) { 182 | for (pos = colname; *pos != 0; pos++) { 183 | if (*pos == '[') { 184 | type_start = pos + 1; 185 | } else if (*pos == ']' && type_start != (const char*)-1) { 186 | key = PyUnicode_FromStringAndSize(type_start, pos - type_start); 187 | if (!key) { 188 | /* creating a string failed, but it is too complicated 189 | * to propagate the error here, we just assume there is 190 | * no converter and proceed */ 191 | break; 192 | } 193 | 194 | converter = _pysqlite_get_converter(key); 195 | Py_DECREF(key); 196 | break; 197 | } 198 | } 199 | } 200 | } 201 | 202 | if (!converter && self->connection->detect_types & PARSE_DECLTYPES) { 203 | decltype = sqlite3_column_decltype(self->statement->st, i); 204 | if (decltype) { 205 | for (pos = decltype;;pos++) { 206 | /* Converter names are split at '(' and blanks. 207 | * This allows 'INTEGER NOT NULL' to be treated as 'INTEGER' and 208 | * 'NUMBER(10)' to be treated as 'NUMBER', for example. 209 | * In other words, it will work as people expect it to work.*/ 210 | if (*pos == ' ' || *pos == '(' || *pos == 0) { 211 | py_decltype = PyUnicode_FromStringAndSize(decltype, pos - decltype); 212 | if (!py_decltype) { 213 | return -1; 214 | } 215 | break; 216 | } 217 | } 218 | 219 | converter = _pysqlite_get_converter(py_decltype); 220 | Py_DECREF(py_decltype); 221 | } 222 | } 223 | 224 | if (!converter) { 225 | converter = Py_None; 226 | } 227 | 228 | if (PyList_Append(self->row_cast_map, converter) != 0) { 229 | if (converter != Py_None) { 230 | Py_DECREF(converter); 231 | } 232 | Py_CLEAR(self->row_cast_map); 233 | 234 | return -1; 235 | } 236 | } 237 | 238 | return 0; 239 | } 240 | 241 | PyObject* _pysqlite_build_column_name(const char* colname) 242 | { 243 | const char* pos; 244 | 245 | if (!colname) { 246 | Py_INCREF(Py_None); 247 | return Py_None; 248 | } 249 | 250 | for (pos = colname;; pos++) { 251 | if (*pos == 0 || *pos == '[') { 252 | if ((*pos == '[') && (pos > colname) && (*(pos-1) == ' ')) { 253 | pos--; 254 | } 255 | return PyUnicode_FromStringAndSize(colname, pos - colname); 256 | } 257 | } 258 | } 259 | 260 | /* 261 | * Returns a row from the currently active SQLite statement 262 | * 263 | * Precondidition: 264 | * - sqlite3_step() has been called before and it returned SQLITE_ROW. 265 | */ 266 | PyObject* _pysqlite_fetch_one_row(pysqlite_Cursor* self) 267 | { 268 | int i, numcols; 269 | PyObject* row; 270 | PyObject* item = NULL; 271 | int coltype; 272 | PyObject* converter; 273 | PyObject* converted; 274 | Py_ssize_t nbytes; 275 | PyObject* buffer; 276 | const char* val_str; 277 | char buf[200]; 278 | const char* colname; 279 | PyObject* buf_bytes; 280 | PyObject* error_obj; 281 | 282 | if (self->reset) { 283 | PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback); 284 | return NULL; 285 | } 286 | 287 | Py_BEGIN_ALLOW_THREADS 288 | numcols = sqlite3_data_count(self->statement->st); 289 | Py_END_ALLOW_THREADS 290 | 291 | row = PyTuple_New(numcols); 292 | if (!row) 293 | return NULL; 294 | 295 | for (i = 0; i < numcols; i++) { 296 | if (self->connection->detect_types) { 297 | converter = PyList_GetItem(self->row_cast_map, i); 298 | if (!converter) { 299 | converter = Py_None; 300 | } 301 | } else { 302 | converter = Py_None; 303 | } 304 | 305 | if (converter != Py_None) { 306 | nbytes = sqlite3_column_bytes(self->statement->st, i); 307 | val_str = (const char*)sqlite3_column_blob(self->statement->st, i); 308 | if (!val_str) { 309 | Py_INCREF(Py_None); 310 | converted = Py_None; 311 | } else { 312 | item = PyBytes_FromStringAndSize(val_str, nbytes); 313 | if (!item) 314 | goto error; 315 | converted = PyObject_CallFunction(converter, "O", item); 316 | Py_DECREF(item); 317 | if (!converted) 318 | break; 319 | } 320 | } else { 321 | Py_BEGIN_ALLOW_THREADS 322 | coltype = sqlite3_column_type(self->statement->st, i); 323 | Py_END_ALLOW_THREADS 324 | if (coltype == SQLITE_NULL) { 325 | Py_INCREF(Py_None); 326 | converted = Py_None; 327 | } else if (coltype == SQLITE_INTEGER) { 328 | converted = _pysqlite_long_from_int64(sqlite3_column_int64(self->statement->st, i)); 329 | } else if (coltype == SQLITE_FLOAT) { 330 | converted = PyFloat_FromDouble(sqlite3_column_double(self->statement->st, i)); 331 | } else if (coltype == SQLITE_TEXT) { 332 | val_str = (const char*)sqlite3_column_text(self->statement->st, i); 333 | nbytes = sqlite3_column_bytes(self->statement->st, i); 334 | if (self->connection->text_factory == (PyObject*)&PyUnicode_Type) { 335 | converted = PyUnicode_FromStringAndSize(val_str, nbytes); 336 | if (!converted) { 337 | #ifdef Py_DEBUG 338 | /* in debug mode, type_call() fails with an assertion 339 | error if an exception is set when it is called */ 340 | PyErr_Clear(); 341 | #endif 342 | colname = sqlite3_column_name(self->statement->st, i); 343 | if (!colname) { 344 | colname = ""; 345 | } 346 | PyOS_snprintf(buf, sizeof(buf) - 1, "Could not decode to UTF-8 column '%s' with text '%s'", 347 | colname , val_str); 348 | buf_bytes = PyByteArray_FromStringAndSize(buf, strlen(buf)); 349 | if (!buf_bytes) { 350 | PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8"); 351 | } else { 352 | error_obj = PyUnicode_FromEncodedObject(buf_bytes, "ascii", "replace"); 353 | if (!error_obj) { 354 | PyErr_SetString(pysqlite_OperationalError, "Could not decode to UTF-8"); 355 | } else { 356 | PyErr_SetObject(pysqlite_OperationalError, error_obj); 357 | Py_DECREF(error_obj); 358 | } 359 | Py_DECREF(buf_bytes); 360 | } 361 | } 362 | } else if (self->connection->text_factory == (PyObject*)&PyBytes_Type) { 363 | converted = PyBytes_FromStringAndSize(val_str, nbytes); 364 | } else if (self->connection->text_factory == (PyObject*)&PyByteArray_Type) { 365 | converted = PyByteArray_FromStringAndSize(val_str, nbytes); 366 | } else { 367 | converted = PyObject_CallFunction(self->connection->text_factory, "y#", val_str, nbytes); 368 | } 369 | } else { 370 | /* coltype == SQLITE_BLOB */ 371 | nbytes = sqlite3_column_bytes(self->statement->st, i); 372 | buffer = PyBytes_FromStringAndSize( 373 | sqlite3_column_blob(self->statement->st, i), nbytes); 374 | if (!buffer) 375 | break; 376 | converted = buffer; 377 | } 378 | } 379 | 380 | if (converted) { 381 | PyTuple_SetItem(row, i, converted); 382 | } else { 383 | Py_INCREF(Py_None); 384 | PyTuple_SetItem(row, i, Py_None); 385 | } 386 | } 387 | 388 | if (PyErr_Occurred()) 389 | goto error; 390 | 391 | return row; 392 | 393 | error: 394 | Py_DECREF(row); 395 | return NULL; 396 | } 397 | 398 | /* 399 | * Checks if a cursor object is usable. 400 | * 401 | * 0 => error; 1 => ok 402 | */ 403 | static int check_cursor(pysqlite_Cursor* cur) 404 | { 405 | if (!cur->initialized) { 406 | PyErr_SetString(pysqlite_ProgrammingError, "Base Cursor.__init__ not called."); 407 | return 0; 408 | } 409 | 410 | if (cur->closed) { 411 | PyErr_SetString(pysqlite_ProgrammingError, "Cannot operate on a closed cursor."); 412 | return 0; 413 | } 414 | 415 | if (cur->locked) { 416 | PyErr_SetString(pysqlite_ProgrammingError, "Recursive use of cursors not allowed."); 417 | return 0; 418 | } 419 | 420 | return pysqlite_check_thread(cur->connection) && pysqlite_check_connection(cur->connection); 421 | } 422 | 423 | PyObject* _pysqlite_query_execute(pysqlite_Cursor* self, int multiple, PyObject* args) 424 | { 425 | PyObject* operation; 426 | const char* operation_cstr; 427 | Py_ssize_t operation_len; 428 | PyObject* parameters_list = NULL; 429 | PyObject* parameters_iter = NULL; 430 | PyObject* parameters = NULL; 431 | int i; 432 | int rc; 433 | PyObject* func_args; 434 | PyObject* result; 435 | int numcols; 436 | int statement_type; 437 | PyObject* descriptor; 438 | PyObject* second_argument = NULL; 439 | 440 | if (!check_cursor(self)) { 441 | goto error; 442 | } 443 | 444 | self->locked = 1; 445 | self->reset = 0; 446 | 447 | Py_CLEAR(self->next_row); 448 | 449 | if (multiple) { 450 | /* executemany() */ 451 | if (!PyArg_ParseTuple(args, "OO", &operation, &second_argument)) { 452 | goto error; 453 | } 454 | 455 | if (!PyUnicode_Check(operation)) { 456 | PyErr_SetString(PyExc_ValueError, "operation parameter must be str"); 457 | goto error; 458 | } 459 | 460 | if (PyIter_Check(second_argument)) { 461 | /* iterator */ 462 | Py_INCREF(second_argument); 463 | parameters_iter = second_argument; 464 | } else { 465 | /* sequence */ 466 | parameters_iter = PyObject_GetIter(second_argument); 467 | if (!parameters_iter) { 468 | goto error; 469 | } 470 | } 471 | } else { 472 | /* execute() */ 473 | if (!PyArg_ParseTuple(args, "O|O", &operation, &second_argument)) { 474 | goto error; 475 | } 476 | 477 | if (!PyUnicode_Check(operation)) { 478 | PyErr_SetString(PyExc_ValueError, "operation parameter must be str"); 479 | goto error; 480 | } 481 | 482 | parameters_list = PyList_New(0); 483 | if (!parameters_list) { 484 | goto error; 485 | } 486 | 487 | if (second_argument == NULL) { 488 | second_argument = PyTuple_New(0); 489 | if (!second_argument) { 490 | goto error; 491 | } 492 | } else { 493 | Py_INCREF(second_argument); 494 | } 495 | if (PyList_Append(parameters_list, second_argument) != 0) { 496 | Py_DECREF(second_argument); 497 | goto error; 498 | } 499 | Py_DECREF(second_argument); 500 | 501 | parameters_iter = PyObject_GetIter(parameters_list); 502 | if (!parameters_iter) { 503 | goto error; 504 | } 505 | } 506 | 507 | if (self->statement != NULL) { 508 | /* There is an active statement */ 509 | pysqlite_statement_reset(self->statement); 510 | } 511 | 512 | operation_cstr = PyUnicode_AsUTF8AndSize(operation, &operation_len); 513 | if (operation_cstr == NULL) 514 | goto error; 515 | 516 | /* reset description and rowcount */ 517 | Py_DECREF(self->description); 518 | Py_INCREF(Py_None); 519 | self->description = Py_None; 520 | self->rowcount = -1L; 521 | 522 | func_args = PyTuple_New(1); 523 | if (!func_args) { 524 | goto error; 525 | } 526 | Py_INCREF(operation); 527 | if (PyTuple_SetItem(func_args, 0, operation) != 0) { 528 | goto error; 529 | } 530 | 531 | if (self->statement) { 532 | (void)pysqlite_statement_reset(self->statement); 533 | Py_DECREF(self->statement); 534 | } 535 | 536 | self->statement = (pysqlite_Statement*)pysqlite_cache_get(self->connection->statement_cache, func_args); 537 | Py_DECREF(func_args); 538 | 539 | if (!self->statement) { 540 | goto error; 541 | } 542 | 543 | if (self->statement->in_use) { 544 | Py_DECREF(self->statement); 545 | self->statement = PyObject_New(pysqlite_Statement, &pysqlite_StatementType); 546 | if (!self->statement) { 547 | goto error; 548 | } 549 | rc = pysqlite_statement_create(self->statement, self->connection, operation); 550 | if (rc != SQLITE_OK) { 551 | Py_CLEAR(self->statement); 552 | goto error; 553 | } 554 | } 555 | 556 | pysqlite_statement_reset(self->statement); 557 | pysqlite_statement_mark_dirty(self->statement); 558 | 559 | statement_type = detect_statement_type(operation_cstr); 560 | if (self->connection->begin_statement) { 561 | switch (statement_type) { 562 | case STATEMENT_UPDATE: 563 | case STATEMENT_DELETE: 564 | case STATEMENT_INSERT: 565 | case STATEMENT_REPLACE: 566 | if (!self->connection->inTransaction) { 567 | result = _pysqlite_connection_begin(self->connection); 568 | if (!result) { 569 | goto error; 570 | } 571 | Py_DECREF(result); 572 | } 573 | break; 574 | case STATEMENT_OTHER: 575 | /* it's a DDL statement or something similar 576 | - we better COMMIT first so it works for all cases */ 577 | if (self->connection->inTransaction) { 578 | result = pysqlite_connection_commit(self->connection, NULL); 579 | if (!result) { 580 | goto error; 581 | } 582 | Py_DECREF(result); 583 | } 584 | break; 585 | case STATEMENT_SELECT: 586 | if (multiple) { 587 | PyErr_SetString(pysqlite_ProgrammingError, 588 | "You cannot execute SELECT statements in executemany()."); 589 | goto error; 590 | } 591 | break; 592 | } 593 | } 594 | 595 | 596 | while (1) { 597 | parameters = PyIter_Next(parameters_iter); 598 | if (!parameters) { 599 | break; 600 | } 601 | 602 | pysqlite_statement_mark_dirty(self->statement); 603 | 604 | pysqlite_statement_bind_parameters(self->statement, parameters); 605 | if (PyErr_Occurred()) { 606 | goto error; 607 | } 608 | 609 | /* Keep trying the SQL statement until the schema stops changing. */ 610 | while (1) { 611 | /* Actually execute the SQL statement. */ 612 | rc = pysqlite_step(self->statement->st, self->connection); 613 | if (PyErr_Occurred()) { 614 | (void)pysqlite_statement_reset(self->statement); 615 | goto error; 616 | } 617 | if (rc == SQLITE_DONE || rc == SQLITE_ROW) { 618 | /* If it worked, let's get out of the loop */ 619 | break; 620 | } 621 | /* Something went wrong. Re-set the statement and try again. */ 622 | rc = pysqlite_statement_reset(self->statement); 623 | if (rc == SQLITE_SCHEMA) { 624 | /* If this was a result of the schema changing, let's try 625 | again. */ 626 | rc = pysqlite_statement_recompile(self->statement, parameters); 627 | if (rc == SQLITE_OK) { 628 | continue; 629 | } else { 630 | /* If the database gave us an error, promote it to Python. */ 631 | (void)pysqlite_statement_reset(self->statement); 632 | _pysqlite_seterror(self->connection->db, NULL); 633 | goto error; 634 | } 635 | } else { 636 | if (PyErr_Occurred()) { 637 | /* there was an error that occurred in a user-defined callback */ 638 | if (_enable_callback_tracebacks) { 639 | PyErr_Print(); 640 | } else { 641 | PyErr_Clear(); 642 | } 643 | } 644 | (void)pysqlite_statement_reset(self->statement); 645 | _pysqlite_seterror(self->connection->db, NULL); 646 | goto error; 647 | } 648 | } 649 | 650 | if (pysqlite_build_row_cast_map(self) != 0) { 651 | PyErr_SetString(pysqlite_OperationalError, "Error while building row_cast_map"); 652 | goto error; 653 | } 654 | 655 | if (rc == SQLITE_ROW || (rc == SQLITE_DONE && statement_type == STATEMENT_SELECT)) { 656 | if (self->description == Py_None) { 657 | Py_BEGIN_ALLOW_THREADS 658 | numcols = sqlite3_column_count(self->statement->st); 659 | Py_END_ALLOW_THREADS 660 | 661 | Py_DECREF(self->description); 662 | self->description = PyTuple_New(numcols); 663 | if (!self->description) { 664 | goto error; 665 | } 666 | for (i = 0; i < numcols; i++) { 667 | descriptor = PyTuple_New(7); 668 | if (!descriptor) { 669 | goto error; 670 | } 671 | PyTuple_SetItem(descriptor, 0, _pysqlite_build_column_name(sqlite3_column_name(self->statement->st, i))); 672 | Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 1, Py_None); 673 | Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 2, Py_None); 674 | Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 3, Py_None); 675 | Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 4, Py_None); 676 | Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 5, Py_None); 677 | Py_INCREF(Py_None); PyTuple_SetItem(descriptor, 6, Py_None); 678 | PyTuple_SetItem(self->description, i, descriptor); 679 | } 680 | } 681 | } 682 | 683 | if (rc == SQLITE_ROW) { 684 | if (multiple) { 685 | PyErr_SetString(pysqlite_ProgrammingError, "executemany() can only execute DML statements."); 686 | goto error; 687 | } 688 | 689 | self->next_row = _pysqlite_fetch_one_row(self); 690 | if (self->next_row == NULL) 691 | goto error; 692 | } else if (rc == SQLITE_DONE && !multiple) { 693 | pysqlite_statement_reset(self->statement); 694 | Py_CLEAR(self->statement); 695 | } 696 | 697 | switch (statement_type) { 698 | case STATEMENT_UPDATE: 699 | case STATEMENT_DELETE: 700 | case STATEMENT_INSERT: 701 | case STATEMENT_REPLACE: 702 | if (self->rowcount == -1L) { 703 | self->rowcount = 0L; 704 | } 705 | self->rowcount += (long)sqlite3_changes(self->connection->db); 706 | } 707 | 708 | Py_DECREF(self->lastrowid); 709 | if (!multiple && statement_type == STATEMENT_INSERT) { 710 | sqlite_int64 lastrowid; 711 | Py_BEGIN_ALLOW_THREADS 712 | lastrowid = sqlite3_last_insert_rowid(self->connection->db); 713 | Py_END_ALLOW_THREADS 714 | self->lastrowid = _pysqlite_long_from_int64(lastrowid); 715 | } else { 716 | Py_INCREF(Py_None); 717 | self->lastrowid = Py_None; 718 | } 719 | 720 | if (multiple) { 721 | pysqlite_statement_reset(self->statement); 722 | } 723 | Py_XDECREF(parameters); 724 | } 725 | 726 | error: 727 | /* just to be sure (implicit ROLLBACKs with ON CONFLICT ROLLBACK/OR 728 | * ROLLBACK could have happened */ 729 | #ifdef SQLITE_VERSION_NUMBER 730 | #if SQLITE_VERSION_NUMBER >= 3002002 731 | if (self->connection && self->connection->db) 732 | self->connection->inTransaction = !sqlite3_get_autocommit(self->connection->db); 733 | #endif 734 | #endif 735 | 736 | Py_XDECREF(parameters); 737 | Py_XDECREF(parameters_iter); 738 | Py_XDECREF(parameters_list); 739 | 740 | self->locked = 0; 741 | 742 | if (PyErr_Occurred()) { 743 | self->rowcount = -1L; 744 | return NULL; 745 | } else { 746 | Py_INCREF(self); 747 | return (PyObject*)self; 748 | } 749 | } 750 | 751 | PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args) 752 | { 753 | return _pysqlite_query_execute(self, 0, args); 754 | } 755 | 756 | PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args) 757 | { 758 | return _pysqlite_query_execute(self, 1, args); 759 | } 760 | 761 | PyObject* pysqlite_cursor_executescript(pysqlite_Cursor* self, PyObject* args) 762 | { 763 | PyObject* script_obj; 764 | PyObject* script_str = NULL; 765 | const char* script_cstr; 766 | sqlite3_stmt* statement; 767 | int rc; 768 | PyObject* result; 769 | 770 | if (!PyArg_ParseTuple(args, "O", &script_obj)) { 771 | return NULL; 772 | } 773 | 774 | if (!check_cursor(self)) { 775 | return NULL; 776 | } 777 | 778 | self->reset = 0; 779 | 780 | if (PyUnicode_Check(script_obj)) { 781 | script_cstr = _PyUnicode_AsString(script_obj); 782 | if (!script_cstr) { 783 | return NULL; 784 | } 785 | } else { 786 | PyErr_SetString(PyExc_ValueError, "script argument must be unicode."); 787 | return NULL; 788 | } 789 | 790 | /* commit first */ 791 | result = pysqlite_connection_commit(self->connection, NULL); 792 | if (!result) { 793 | goto error; 794 | } 795 | Py_DECREF(result); 796 | 797 | while (1) { 798 | Py_BEGIN_ALLOW_THREADS 799 | rc = sqlite3_prepare(self->connection->db, 800 | script_cstr, 801 | -1, 802 | &statement, 803 | &script_cstr); 804 | Py_END_ALLOW_THREADS 805 | if (rc != SQLITE_OK) { 806 | _pysqlite_seterror(self->connection->db, NULL); 807 | goto error; 808 | } 809 | 810 | /* execute statement, and ignore results of SELECT statements */ 811 | rc = SQLITE_ROW; 812 | while (rc == SQLITE_ROW) { 813 | rc = pysqlite_step(statement, self->connection); 814 | if (PyErr_Occurred()) { 815 | (void)sqlite3_finalize(statement); 816 | goto error; 817 | } 818 | } 819 | 820 | if (rc != SQLITE_DONE) { 821 | (void)sqlite3_finalize(statement); 822 | _pysqlite_seterror(self->connection->db, NULL); 823 | goto error; 824 | } 825 | 826 | rc = sqlite3_finalize(statement); 827 | if (rc != SQLITE_OK) { 828 | _pysqlite_seterror(self->connection->db, NULL); 829 | goto error; 830 | } 831 | 832 | if (*script_cstr == (char)0) { 833 | break; 834 | } 835 | } 836 | 837 | error: 838 | Py_XDECREF(script_str); 839 | 840 | if (PyErr_Occurred()) { 841 | return NULL; 842 | } else { 843 | Py_INCREF(self); 844 | return (PyObject*)self; 845 | } 846 | } 847 | 848 | PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self) 849 | { 850 | Py_INCREF(self); 851 | return (PyObject*)self; 852 | } 853 | 854 | PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self) 855 | { 856 | PyObject* next_row_tuple; 857 | PyObject* next_row; 858 | int rc; 859 | 860 | if (!check_cursor(self)) { 861 | return NULL; 862 | } 863 | 864 | if (self->reset) { 865 | PyErr_SetString(pysqlite_InterfaceError, errmsg_fetch_across_rollback); 866 | return NULL; 867 | } 868 | 869 | if (!self->next_row) { 870 | if (self->statement) { 871 | (void)pysqlite_statement_reset(self->statement); 872 | Py_CLEAR(self->statement); 873 | } 874 | return NULL; 875 | } 876 | 877 | next_row_tuple = self->next_row; 878 | assert(next_row_tuple != NULL); 879 | self->next_row = NULL; 880 | 881 | if (self->row_factory != Py_None) { 882 | next_row = PyObject_CallFunction(self->row_factory, "OO", self, next_row_tuple); 883 | if (next_row == NULL) { 884 | self->next_row = next_row_tuple; 885 | return NULL; 886 | } 887 | Py_DECREF(next_row_tuple); 888 | } else { 889 | next_row = next_row_tuple; 890 | } 891 | 892 | if (self->statement) { 893 | rc = pysqlite_step(self->statement->st, self->connection); 894 | if (PyErr_Occurred()) { 895 | (void)pysqlite_statement_reset(self->statement); 896 | Py_DECREF(next_row); 897 | return NULL; 898 | } 899 | if (rc != SQLITE_DONE && rc != SQLITE_ROW) { 900 | (void)pysqlite_statement_reset(self->statement); 901 | Py_DECREF(next_row); 902 | _pysqlite_seterror(self->connection->db, NULL); 903 | return NULL; 904 | } 905 | 906 | if (rc == SQLITE_ROW) { 907 | self->next_row = _pysqlite_fetch_one_row(self); 908 | if (self->next_row == NULL) { 909 | (void)pysqlite_statement_reset(self->statement); 910 | return NULL; 911 | } 912 | } 913 | } 914 | 915 | return next_row; 916 | } 917 | 918 | PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args) 919 | { 920 | PyObject* row; 921 | 922 | row = pysqlite_cursor_iternext(self); 923 | if (!row && !PyErr_Occurred()) { 924 | Py_INCREF(Py_None); 925 | return Py_None; 926 | } 927 | 928 | return row; 929 | } 930 | 931 | PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs) 932 | { 933 | static char *kwlist[] = {"size", NULL, NULL}; 934 | 935 | PyObject* row; 936 | PyObject* list; 937 | int maxrows = self->arraysize; 938 | int counter = 0; 939 | 940 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i:fetchmany", kwlist, &maxrows)) { 941 | return NULL; 942 | } 943 | 944 | list = PyList_New(0); 945 | if (!list) { 946 | return NULL; 947 | } 948 | 949 | /* just make sure we enter the loop */ 950 | row = Py_None; 951 | 952 | while (row) { 953 | row = pysqlite_cursor_iternext(self); 954 | if (row) { 955 | PyList_Append(list, row); 956 | Py_DECREF(row); 957 | } else { 958 | break; 959 | } 960 | 961 | if (++counter == maxrows) { 962 | break; 963 | } 964 | } 965 | 966 | if (PyErr_Occurred()) { 967 | Py_DECREF(list); 968 | return NULL; 969 | } else { 970 | return list; 971 | } 972 | } 973 | 974 | PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args) 975 | { 976 | PyObject* row; 977 | PyObject* list; 978 | 979 | list = PyList_New(0); 980 | if (!list) { 981 | return NULL; 982 | } 983 | 984 | /* just make sure we enter the loop */ 985 | row = (PyObject*)Py_None; 986 | 987 | while (row) { 988 | row = pysqlite_cursor_iternext(self); 989 | if (row) { 990 | PyList_Append(list, row); 991 | Py_DECREF(row); 992 | } 993 | } 994 | 995 | if (PyErr_Occurred()) { 996 | Py_DECREF(list); 997 | return NULL; 998 | } else { 999 | return list; 1000 | } 1001 | } 1002 | 1003 | PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args) 1004 | { 1005 | /* don't care, return None */ 1006 | Py_INCREF(Py_None); 1007 | return Py_None; 1008 | } 1009 | 1010 | PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args) 1011 | { 1012 | if (!pysqlite_check_thread(self->connection) || !pysqlite_check_connection(self->connection)) { 1013 | return NULL; 1014 | } 1015 | 1016 | if (self->statement) { 1017 | (void)pysqlite_statement_reset(self->statement); 1018 | Py_CLEAR(self->statement); 1019 | } 1020 | 1021 | self->closed = 1; 1022 | 1023 | Py_INCREF(Py_None); 1024 | return Py_None; 1025 | } 1026 | 1027 | static PyMethodDef cursor_methods[] = { 1028 | {"execute", (PyCFunction)pysqlite_cursor_execute, METH_VARARGS, 1029 | PyDoc_STR("Executes a SQL statement.")}, 1030 | {"executemany", (PyCFunction)pysqlite_cursor_executemany, METH_VARARGS, 1031 | PyDoc_STR("Repeatedly executes a SQL statement.")}, 1032 | {"executescript", (PyCFunction)pysqlite_cursor_executescript, METH_VARARGS, 1033 | PyDoc_STR("Executes a multiple SQL statements at once. Non-standard.")}, 1034 | {"fetchone", (PyCFunction)pysqlite_cursor_fetchone, METH_NOARGS, 1035 | PyDoc_STR("Fetches one row from the resultset.")}, 1036 | {"fetchmany", (PyCFunction)pysqlite_cursor_fetchmany, METH_VARARGS|METH_KEYWORDS, 1037 | PyDoc_STR("Fetches several rows from the resultset.")}, 1038 | {"fetchall", (PyCFunction)pysqlite_cursor_fetchall, METH_NOARGS, 1039 | PyDoc_STR("Fetches all rows from the resultset.")}, 1040 | {"close", (PyCFunction)pysqlite_cursor_close, METH_NOARGS, 1041 | PyDoc_STR("Closes the cursor.")}, 1042 | {"setinputsizes", (PyCFunction)pysqlite_noop, METH_VARARGS, 1043 | PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")}, 1044 | {"setoutputsize", (PyCFunction)pysqlite_noop, METH_VARARGS, 1045 | PyDoc_STR("Required by DB-API. Does nothing in pysqlite.")}, 1046 | {NULL, NULL} 1047 | }; 1048 | 1049 | static struct PyMemberDef cursor_members[] = 1050 | { 1051 | {"connection", T_OBJECT, offsetof(pysqlite_Cursor, connection), READONLY}, 1052 | {"description", T_OBJECT, offsetof(pysqlite_Cursor, description), READONLY}, 1053 | {"arraysize", T_INT, offsetof(pysqlite_Cursor, arraysize), 0}, 1054 | {"lastrowid", T_OBJECT, offsetof(pysqlite_Cursor, lastrowid), READONLY}, 1055 | {"rowcount", T_LONG, offsetof(pysqlite_Cursor, rowcount), READONLY}, 1056 | {"row_factory", T_OBJECT, offsetof(pysqlite_Cursor, row_factory), 0}, 1057 | {NULL} 1058 | }; 1059 | 1060 | static char cursor_doc[] = 1061 | PyDoc_STR("SQLite database cursor class."); 1062 | 1063 | PyTypeObject pysqlite_CursorType = { 1064 | PyVarObject_HEAD_INIT(NULL, 0) 1065 | MODULE_NAME ".Cursor", /* tp_name */ 1066 | sizeof(pysqlite_Cursor), /* tp_basicsize */ 1067 | 0, /* tp_itemsize */ 1068 | (destructor)pysqlite_cursor_dealloc, /* tp_dealloc */ 1069 | 0, /* tp_print */ 1070 | 0, /* tp_getattr */ 1071 | 0, /* tp_setattr */ 1072 | 0, /* tp_reserved */ 1073 | 0, /* tp_repr */ 1074 | 0, /* tp_as_number */ 1075 | 0, /* tp_as_sequence */ 1076 | 0, /* tp_as_mapping */ 1077 | 0, /* tp_hash */ 1078 | 0, /* tp_call */ 1079 | 0, /* tp_str */ 1080 | 0, /* tp_getattro */ 1081 | 0, /* tp_setattro */ 1082 | 0, /* tp_as_buffer */ 1083 | Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 1084 | cursor_doc, /* tp_doc */ 1085 | 0, /* tp_traverse */ 1086 | 0, /* tp_clear */ 1087 | 0, /* tp_richcompare */ 1088 | offsetof(pysqlite_Cursor, in_weakreflist), /* tp_weaklistoffset */ 1089 | (getiterfunc)pysqlite_cursor_getiter, /* tp_iter */ 1090 | (iternextfunc)pysqlite_cursor_iternext, /* tp_iternext */ 1091 | cursor_methods, /* tp_methods */ 1092 | cursor_members, /* tp_members */ 1093 | 0, /* tp_getset */ 1094 | 0, /* tp_base */ 1095 | 0, /* tp_dict */ 1096 | 0, /* tp_descr_get */ 1097 | 0, /* tp_descr_set */ 1098 | 0, /* tp_dictoffset */ 1099 | (initproc)pysqlite_cursor_init, /* tp_init */ 1100 | 0, /* tp_alloc */ 1101 | 0, /* tp_new */ 1102 | 0 /* tp_free */ 1103 | }; 1104 | 1105 | extern int pysqlite_cursor_setup_types(void) 1106 | { 1107 | pysqlite_CursorType.tp_new = PyType_GenericNew; 1108 | return PyType_Ready(&pysqlite_CursorType); 1109 | } 1110 | -------------------------------------------------------------------------------- /src/python3/cursor.h: -------------------------------------------------------------------------------- 1 | /* cursor.h - definitions for the cursor type 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_CURSOR_H 25 | #define PYSQLITE_CURSOR_H 26 | #include "Python.h" 27 | 28 | #include "statement.h" 29 | #include "connection.h" 30 | #include "module.h" 31 | 32 | typedef struct 33 | { 34 | PyObject_HEAD 35 | pysqlite_Connection* connection; 36 | PyObject* description; 37 | PyObject* row_cast_map; 38 | int arraysize; 39 | PyObject* lastrowid; 40 | long rowcount; 41 | PyObject* row_factory; 42 | pysqlite_Statement* statement; 43 | int closed; 44 | int reset; 45 | int locked; 46 | int initialized; 47 | 48 | /* the next row to be returned, NULL if no next row available */ 49 | PyObject* next_row; 50 | 51 | PyObject* in_weakreflist; /* List of weak references */ 52 | } pysqlite_Cursor; 53 | 54 | typedef enum { 55 | STATEMENT_INVALID, STATEMENT_INSERT, STATEMENT_DELETE, 56 | STATEMENT_UPDATE, STATEMENT_REPLACE, STATEMENT_SELECT, 57 | STATEMENT_OTHER 58 | } pysqlite_StatementKind; 59 | 60 | extern PyTypeObject pysqlite_CursorType; 61 | 62 | PyObject* pysqlite_cursor_execute(pysqlite_Cursor* self, PyObject* args); 63 | PyObject* pysqlite_cursor_executemany(pysqlite_Cursor* self, PyObject* args); 64 | PyObject* pysqlite_cursor_getiter(pysqlite_Cursor *self); 65 | PyObject* pysqlite_cursor_iternext(pysqlite_Cursor *self); 66 | PyObject* pysqlite_cursor_fetchone(pysqlite_Cursor* self, PyObject* args); 67 | PyObject* pysqlite_cursor_fetchmany(pysqlite_Cursor* self, PyObject* args, PyObject* kwargs); 68 | PyObject* pysqlite_cursor_fetchall(pysqlite_Cursor* self, PyObject* args); 69 | PyObject* pysqlite_noop(pysqlite_Connection* self, PyObject* args); 70 | PyObject* pysqlite_cursor_close(pysqlite_Cursor* self, PyObject* args); 71 | 72 | int pysqlite_cursor_setup_types(void); 73 | 74 | #define UNKNOWN (-1) 75 | #endif 76 | -------------------------------------------------------------------------------- /src/python3/microprotocols.c: -------------------------------------------------------------------------------- 1 | /* microprotocols.c - minimalist and non-validating protocols implementation 2 | * 3 | * Copyright (C) 2003-2004 Federico Di Gregorio 4 | * 5 | * This file is part of psycopg and was adapted for pysqlite. Federico Di 6 | * Gregorio gave the permission to use it within pysqlite under the following 7 | * license: 8 | * 9 | * This software is provided 'as-is', without any express or implied 10 | * warranty. In no event will the authors be held liable for any damages 11 | * arising from the use of this software. 12 | * 13 | * Permission is granted to anyone to use this software for any purpose, 14 | * including commercial applications, and to alter it and redistribute it 15 | * freely, subject to the following restrictions: 16 | * 17 | * 1. The origin of this software must not be misrepresented; you must not 18 | * claim that you wrote the original software. If you use this software 19 | * in a product, an acknowledgment in the product documentation would be 20 | * appreciated but is not required. 21 | * 2. Altered source versions must be plainly marked as such, and must not be 22 | * misrepresented as being the original software. 23 | * 3. This notice may not be removed or altered from any source distribution. 24 | */ 25 | 26 | #include 27 | #include 28 | 29 | #include "cursor.h" 30 | #include "microprotocols.h" 31 | #include "prepare_protocol.h" 32 | 33 | 34 | /** the adapters registry **/ 35 | 36 | PyObject *psyco_adapters; 37 | 38 | /* pysqlite_microprotocols_init - initialize the adapters dictionary */ 39 | 40 | int 41 | pysqlite_microprotocols_init(PyObject *dict) 42 | { 43 | /* create adapters dictionary and put it in module namespace */ 44 | if ((psyco_adapters = PyDict_New()) == NULL) { 45 | return -1; 46 | } 47 | 48 | return PyDict_SetItemString(dict, "adapters", psyco_adapters); 49 | } 50 | 51 | 52 | /* pysqlite_microprotocols_add - add a reverse type-caster to the dictionary */ 53 | 54 | int 55 | pysqlite_microprotocols_add(PyTypeObject *type, PyObject *proto, PyObject *cast) 56 | { 57 | PyObject* key; 58 | int rc; 59 | 60 | if (proto == NULL) proto = (PyObject*)&pysqlite_PrepareProtocolType; 61 | 62 | key = Py_BuildValue("(OO)", (PyObject*)type, proto); 63 | if (!key) { 64 | return -1; 65 | } 66 | 67 | rc = PyDict_SetItem(psyco_adapters, key, cast); 68 | Py_DECREF(key); 69 | 70 | return rc; 71 | } 72 | 73 | /* pysqlite_microprotocols_adapt - adapt an object to the built-in protocol */ 74 | 75 | PyObject * 76 | pysqlite_microprotocols_adapt(PyObject *obj, PyObject *proto, PyObject *alt) 77 | { 78 | PyObject *adapter, *key; 79 | 80 | /* we don't check for exact type conformance as specified in PEP 246 81 | because the pysqlite_PrepareProtocolType type is abstract and there is no 82 | way to get a quotable object to be its instance */ 83 | 84 | /* look for an adapter in the registry */ 85 | key = Py_BuildValue("(OO)", (PyObject*)obj->ob_type, proto); 86 | if (!key) { 87 | return NULL; 88 | } 89 | adapter = PyDict_GetItem(psyco_adapters, key); 90 | Py_DECREF(key); 91 | if (adapter) { 92 | PyObject *adapted = PyObject_CallFunctionObjArgs(adapter, obj, NULL); 93 | return adapted; 94 | } 95 | 96 | /* try to have the protocol adapt this object*/ 97 | if (PyObject_HasAttrString(proto, "__adapt__")) { 98 | _Py_IDENTIFIER(__adapt__); 99 | PyObject *adapted = _PyObject_CallMethodId(proto, &PyId___adapt__, "O", obj); 100 | 101 | if (adapted) { 102 | if (adapted != Py_None) { 103 | return adapted; 104 | } else { 105 | Py_DECREF(adapted); 106 | } 107 | } 108 | 109 | if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) 110 | return NULL; 111 | } 112 | 113 | /* and finally try to have the object adapt itself */ 114 | if (PyObject_HasAttrString(obj, "__conform__")) { 115 | _Py_IDENTIFIER(__conform__); 116 | PyObject *adapted = _PyObject_CallMethodId(obj, &PyId___conform__,"O", proto); 117 | 118 | if (adapted) { 119 | if (adapted != Py_None) { 120 | return adapted; 121 | } else { 122 | Py_DECREF(adapted); 123 | } 124 | } 125 | 126 | if (PyErr_Occurred() && !PyErr_ExceptionMatches(PyExc_TypeError)) { 127 | return NULL; 128 | } 129 | } 130 | 131 | /* else set the right exception and return NULL */ 132 | PyErr_SetString(pysqlite_ProgrammingError, "can't adapt"); 133 | return NULL; 134 | } 135 | 136 | /** module-level functions **/ 137 | 138 | PyObject * 139 | pysqlite_adapt(pysqlite_Cursor *self, PyObject *args) 140 | { 141 | PyObject *obj, *alt = NULL; 142 | PyObject *proto = (PyObject*)&pysqlite_PrepareProtocolType; 143 | 144 | if (!PyArg_ParseTuple(args, "O|OO", &obj, &proto, &alt)) return NULL; 145 | return pysqlite_microprotocols_adapt(obj, proto, alt); 146 | } 147 | -------------------------------------------------------------------------------- /src/python3/microprotocols.h: -------------------------------------------------------------------------------- 1 | /* microprotocols.c - definitions for minimalist and non-validating protocols 2 | * 3 | * Copyright (C) 2003-2004 Federico Di Gregorio 4 | * 5 | * This file is part of psycopg and was adapted for pysqlite. Federico Di 6 | * Gregorio gave the permission to use it within pysqlite under the following 7 | * license: 8 | * 9 | * This software is provided 'as-is', without any express or implied 10 | * warranty. In no event will the authors be held liable for any damages 11 | * arising from the use of this software. 12 | * 13 | * Permission is granted to anyone to use this software for any purpose, 14 | * including commercial applications, and to alter it and redistribute it 15 | * freely, subject to the following restrictions: 16 | * 17 | * 1. The origin of this software must not be misrepresented; you must not 18 | * claim that you wrote the original software. If you use this software 19 | * in a product, an acknowledgment in the product documentation would be 20 | * appreciated but is not required. 21 | * 2. Altered source versions must be plainly marked as such, and must not be 22 | * misrepresented as being the original software. 23 | * 3. This notice may not be removed or altered from any source distribution. 24 | */ 25 | 26 | #ifndef PSYCOPG_MICROPROTOCOLS_H 27 | #define PSYCOPG_MICROPROTOCOLS_H 1 28 | 29 | #include 30 | 31 | /** adapters registry **/ 32 | 33 | extern PyObject *psyco_adapters; 34 | 35 | /** the names of the three mandatory methods **/ 36 | 37 | #define MICROPROTOCOLS_GETQUOTED_NAME "getquoted" 38 | #define MICROPROTOCOLS_GETSTRING_NAME "getstring" 39 | #define MICROPROTOCOLS_GETBINARY_NAME "getbinary" 40 | 41 | /** exported functions **/ 42 | 43 | /* used by module.c to init the microprotocols system */ 44 | extern int pysqlite_microprotocols_init(PyObject *dict); 45 | extern int pysqlite_microprotocols_add( 46 | PyTypeObject *type, PyObject *proto, PyObject *cast); 47 | extern PyObject *pysqlite_microprotocols_adapt( 48 | PyObject *obj, PyObject *proto, PyObject *alt); 49 | 50 | extern PyObject * 51 | pysqlite_adapt(pysqlite_Cursor* self, PyObject *args); 52 | #define pysqlite_adapt_doc \ 53 | "adapt(obj, protocol, alternate) -> adapt obj to given protocol. Non-standard." 54 | 55 | #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ 56 | -------------------------------------------------------------------------------- /src/python3/module.c: -------------------------------------------------------------------------------- 1 | /* module.c - the module itself 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "connection.h" 25 | #include "statement.h" 26 | #include "cursor.h" 27 | #include "cache.h" 28 | #include "prepare_protocol.h" 29 | #include "microprotocols.h" 30 | #include "row.h" 31 | 32 | #if SQLITE_VERSION_NUMBER >= 3003003 33 | #define HAVE_SHARED_CACHE 34 | #endif 35 | 36 | /* static objects at module-level */ 37 | 38 | PyObject* pysqlite_Error, *pysqlite_Warning, *pysqlite_InterfaceError, *pysqlite_DatabaseError, 39 | *pysqlite_InternalError, *pysqlite_OperationalError, *pysqlite_ProgrammingError, 40 | *pysqlite_IntegrityError, *pysqlite_DataError, *pysqlite_NotSupportedError; 41 | 42 | PyObject* converters; 43 | int _enable_callback_tracebacks; 44 | int pysqlite_BaseTypeAdapted; 45 | 46 | static PyObject* module_connect(PyObject* self, PyObject* args, PyObject* 47 | kwargs) 48 | { 49 | /* Python seems to have no way of extracting a single keyword-arg at 50 | * C-level, so this code is redundant with the one in connection_init in 51 | * connection.c and must always be copied from there ... */ 52 | 53 | static char *kwlist[] = { 54 | "database", "timeout", "detect_types", "isolation_level", 55 | "check_same_thread", "factory", "cached_statements", "uri", 56 | NULL 57 | }; 58 | char* database; 59 | int detect_types = 0; 60 | PyObject* isolation_level; 61 | PyObject* factory = NULL; 62 | int check_same_thread = 1; 63 | int cached_statements; 64 | int uri = 0; 65 | double timeout = 5.0; 66 | 67 | PyObject* result; 68 | 69 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|diOiOip", kwlist, 70 | &database, &timeout, &detect_types, 71 | &isolation_level, &check_same_thread, 72 | &factory, &cached_statements, &uri)) 73 | { 74 | return NULL; 75 | } 76 | 77 | if (factory == NULL) { 78 | factory = (PyObject*)&pysqlite_ConnectionType; 79 | } 80 | 81 | result = PyObject_Call(factory, args, kwargs); 82 | 83 | return result; 84 | } 85 | 86 | PyDoc_STRVAR(module_connect_doc, 87 | "connect(database[, timeout, detect_types, isolation_level,\n\ 88 | check_same_thread, factory, cached_statements, uri])\n\ 89 | \n\ 90 | Opens a connection to the SQLite database file *database*. You can use\n\ 91 | \":memory:\" to open a database connection to a database that resides in\n\ 92 | RAM instead of on disk."); 93 | 94 | static PyObject* module_complete(PyObject* self, PyObject* args, PyObject* 95 | kwargs) 96 | { 97 | static char *kwlist[] = {"statement", NULL, NULL}; 98 | char* statement; 99 | 100 | PyObject* result; 101 | 102 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s", kwlist, &statement)) 103 | { 104 | return NULL; 105 | } 106 | 107 | if (sqlite3_complete(statement)) { 108 | result = Py_True; 109 | } else { 110 | result = Py_False; 111 | } 112 | 113 | Py_INCREF(result); 114 | 115 | return result; 116 | } 117 | 118 | PyDoc_STRVAR(module_complete_doc, 119 | "complete_statement(sql)\n\ 120 | \n\ 121 | Checks if a string contains a complete SQL statement. Non-standard."); 122 | 123 | #ifdef HAVE_SHARED_CACHE 124 | static PyObject* module_enable_shared_cache(PyObject* self, PyObject* args, PyObject* 125 | kwargs) 126 | { 127 | static char *kwlist[] = {"do_enable", NULL, NULL}; 128 | int do_enable; 129 | int rc; 130 | 131 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", kwlist, &do_enable)) 132 | { 133 | return NULL; 134 | } 135 | 136 | rc = sqlite3_enable_shared_cache(do_enable); 137 | 138 | if (rc != SQLITE_OK) { 139 | PyErr_SetString(pysqlite_OperationalError, "Changing the shared_cache flag failed"); 140 | return NULL; 141 | } else { 142 | Py_INCREF(Py_None); 143 | return Py_None; 144 | } 145 | } 146 | 147 | PyDoc_STRVAR(module_enable_shared_cache_doc, 148 | "enable_shared_cache(do_enable)\n\ 149 | \n\ 150 | Enable or disable shared cache mode for the calling thread.\n\ 151 | Experimental/Non-standard."); 152 | #endif /* HAVE_SHARED_CACHE */ 153 | 154 | static PyObject* module_register_adapter(PyObject* self, PyObject* args) 155 | { 156 | PyTypeObject* type; 157 | PyObject* caster; 158 | int rc; 159 | 160 | if (!PyArg_ParseTuple(args, "OO", &type, &caster)) { 161 | return NULL; 162 | } 163 | 164 | /* a basic type is adapted; there's a performance optimization if that's not the case 165 | * (99 % of all usages) */ 166 | if (type == &PyLong_Type || type == &PyFloat_Type 167 | || type == &PyUnicode_Type || type == &PyByteArray_Type) { 168 | pysqlite_BaseTypeAdapted = 1; 169 | } 170 | 171 | rc = pysqlite_microprotocols_add(type, (PyObject*)&pysqlite_PrepareProtocolType, caster); 172 | if (rc == -1) 173 | return NULL; 174 | 175 | Py_INCREF(Py_None); 176 | return Py_None; 177 | } 178 | 179 | PyDoc_STRVAR(module_register_adapter_doc, 180 | "register_adapter(type, callable)\n\ 181 | \n\ 182 | Registers an adapter with pysqlite's adapter registry. Non-standard."); 183 | 184 | static PyObject* module_register_converter(PyObject* self, PyObject* args) 185 | { 186 | PyObject* orig_name; 187 | PyObject* name = NULL; 188 | PyObject* callable; 189 | PyObject* retval = NULL; 190 | _Py_IDENTIFIER(upper); 191 | 192 | if (!PyArg_ParseTuple(args, "UO", &orig_name, &callable)) { 193 | return NULL; 194 | } 195 | 196 | /* convert the name to upper case */ 197 | name = _PyObject_CallMethodId(orig_name, &PyId_upper, ""); 198 | if (!name) { 199 | goto error; 200 | } 201 | 202 | if (PyDict_SetItem(converters, name, callable) != 0) { 203 | goto error; 204 | } 205 | 206 | Py_INCREF(Py_None); 207 | retval = Py_None; 208 | error: 209 | Py_XDECREF(name); 210 | return retval; 211 | } 212 | 213 | PyDoc_STRVAR(module_register_converter_doc, 214 | "register_converter(typename, callable)\n\ 215 | \n\ 216 | Registers a converter with pysqlite. Non-standard."); 217 | 218 | static PyObject* enable_callback_tracebacks(PyObject* self, PyObject* args) 219 | { 220 | if (!PyArg_ParseTuple(args, "i", &_enable_callback_tracebacks)) { 221 | return NULL; 222 | } 223 | 224 | Py_INCREF(Py_None); 225 | return Py_None; 226 | } 227 | 228 | PyDoc_STRVAR(enable_callback_tracebacks_doc, 229 | "enable_callback_tracebacks(flag)\n\ 230 | \n\ 231 | Enable or disable callback functions throwing errors to stderr."); 232 | 233 | static void converters_init(PyObject* dict) 234 | { 235 | converters = PyDict_New(); 236 | if (!converters) { 237 | return; 238 | } 239 | 240 | PyDict_SetItemString(dict, "converters", converters); 241 | } 242 | 243 | static PyMethodDef module_methods[] = { 244 | {"connect", (PyCFunction)module_connect, 245 | METH_VARARGS | METH_KEYWORDS, module_connect_doc}, 246 | {"complete_statement", (PyCFunction)module_complete, 247 | METH_VARARGS | METH_KEYWORDS, module_complete_doc}, 248 | #ifdef HAVE_SHARED_CACHE 249 | {"enable_shared_cache", (PyCFunction)module_enable_shared_cache, 250 | METH_VARARGS | METH_KEYWORDS, module_enable_shared_cache_doc}, 251 | #endif 252 | {"register_adapter", (PyCFunction)module_register_adapter, 253 | METH_VARARGS, module_register_adapter_doc}, 254 | {"register_converter", (PyCFunction)module_register_converter, 255 | METH_VARARGS, module_register_converter_doc}, 256 | {"adapt", (PyCFunction)pysqlite_adapt, METH_VARARGS, 257 | pysqlite_adapt_doc}, 258 | {"enable_callback_tracebacks", (PyCFunction)enable_callback_tracebacks, 259 | METH_VARARGS, enable_callback_tracebacks_doc}, 260 | {NULL, NULL} 261 | }; 262 | 263 | struct _IntConstantPair { 264 | char* constant_name; 265 | int constant_value; 266 | }; 267 | 268 | typedef struct _IntConstantPair IntConstantPair; 269 | 270 | static IntConstantPair _int_constants[] = { 271 | {"PARSE_DECLTYPES", PARSE_DECLTYPES}, 272 | {"PARSE_COLNAMES", PARSE_COLNAMES}, 273 | 274 | {"SQLITE_OK", SQLITE_OK}, 275 | {"SQLITE_DENY", SQLITE_DENY}, 276 | {"SQLITE_IGNORE", SQLITE_IGNORE}, 277 | {"SQLITE_CREATE_INDEX", SQLITE_CREATE_INDEX}, 278 | {"SQLITE_CREATE_TABLE", SQLITE_CREATE_TABLE}, 279 | {"SQLITE_CREATE_TEMP_INDEX", SQLITE_CREATE_TEMP_INDEX}, 280 | {"SQLITE_CREATE_TEMP_TABLE", SQLITE_CREATE_TEMP_TABLE}, 281 | {"SQLITE_CREATE_TEMP_TRIGGER", SQLITE_CREATE_TEMP_TRIGGER}, 282 | {"SQLITE_CREATE_TEMP_VIEW", SQLITE_CREATE_TEMP_VIEW}, 283 | {"SQLITE_CREATE_TRIGGER", SQLITE_CREATE_TRIGGER}, 284 | {"SQLITE_CREATE_VIEW", SQLITE_CREATE_VIEW}, 285 | {"SQLITE_DELETE", SQLITE_DELETE}, 286 | {"SQLITE_DROP_INDEX", SQLITE_DROP_INDEX}, 287 | {"SQLITE_DROP_TABLE", SQLITE_DROP_TABLE}, 288 | {"SQLITE_DROP_TEMP_INDEX", SQLITE_DROP_TEMP_INDEX}, 289 | {"SQLITE_DROP_TEMP_TABLE", SQLITE_DROP_TEMP_TABLE}, 290 | {"SQLITE_DROP_TEMP_TRIGGER", SQLITE_DROP_TEMP_TRIGGER}, 291 | {"SQLITE_DROP_TEMP_VIEW", SQLITE_DROP_TEMP_VIEW}, 292 | {"SQLITE_DROP_TRIGGER", SQLITE_DROP_TRIGGER}, 293 | {"SQLITE_DROP_VIEW", SQLITE_DROP_VIEW}, 294 | {"SQLITE_INSERT", SQLITE_INSERT}, 295 | {"SQLITE_PRAGMA", SQLITE_PRAGMA}, 296 | {"SQLITE_READ", SQLITE_READ}, 297 | {"SQLITE_SELECT", SQLITE_SELECT}, 298 | {"SQLITE_TRANSACTION", SQLITE_TRANSACTION}, 299 | {"SQLITE_UPDATE", SQLITE_UPDATE}, 300 | {"SQLITE_ATTACH", SQLITE_ATTACH}, 301 | {"SQLITE_DETACH", SQLITE_DETACH}, 302 | #if SQLITE_VERSION_NUMBER >= 3002001 303 | {"SQLITE_ALTER_TABLE", SQLITE_ALTER_TABLE}, 304 | {"SQLITE_REINDEX", SQLITE_REINDEX}, 305 | #endif 306 | #if SQLITE_VERSION_NUMBER >= 3003000 307 | {"SQLITE_ANALYZE", SQLITE_ANALYZE}, 308 | #endif 309 | {(char*)NULL, 0} 310 | }; 311 | 312 | 313 | static struct PyModuleDef _sqlite3module = { 314 | PyModuleDef_HEAD_INIT, 315 | "_sqlite3", 316 | NULL, 317 | -1, 318 | module_methods, 319 | NULL, 320 | NULL, 321 | NULL, 322 | NULL 323 | }; 324 | 325 | PyMODINIT_FUNC PyInit__sqlite3(void) 326 | { 327 | PyObject *module, *dict; 328 | PyObject *tmp_obj; 329 | int i; 330 | 331 | module = PyModule_Create(&_sqlite3module); 332 | 333 | if (!module || 334 | (pysqlite_row_setup_types() < 0) || 335 | (pysqlite_cursor_setup_types() < 0) || 336 | (pysqlite_connection_setup_types() < 0) || 337 | (pysqlite_cache_setup_types() < 0) || 338 | (pysqlite_statement_setup_types() < 0) || 339 | (pysqlite_prepare_protocol_setup_types() < 0) 340 | ) { 341 | Py_XDECREF(module); 342 | return NULL; 343 | } 344 | 345 | Py_INCREF(&pysqlite_ConnectionType); 346 | PyModule_AddObject(module, "Connection", (PyObject*) &pysqlite_ConnectionType); 347 | Py_INCREF(&pysqlite_CursorType); 348 | PyModule_AddObject(module, "Cursor", (PyObject*) &pysqlite_CursorType); 349 | Py_INCREF(&pysqlite_CacheType); 350 | PyModule_AddObject(module, "Statement", (PyObject*)&pysqlite_StatementType); 351 | Py_INCREF(&pysqlite_StatementType); 352 | PyModule_AddObject(module, "Cache", (PyObject*) &pysqlite_CacheType); 353 | Py_INCREF(&pysqlite_PrepareProtocolType); 354 | PyModule_AddObject(module, "PrepareProtocol", (PyObject*) &pysqlite_PrepareProtocolType); 355 | Py_INCREF(&pysqlite_RowType); 356 | PyModule_AddObject(module, "Row", (PyObject*) &pysqlite_RowType); 357 | 358 | if (!(dict = PyModule_GetDict(module))) { 359 | goto error; 360 | } 361 | 362 | /*** Create DB-API Exception hierarchy */ 363 | 364 | if (!(pysqlite_Error = PyErr_NewException(MODULE_NAME ".Error", PyExc_Exception, NULL))) { 365 | goto error; 366 | } 367 | PyDict_SetItemString(dict, "Error", pysqlite_Error); 368 | 369 | if (!(pysqlite_Warning = PyErr_NewException(MODULE_NAME ".Warning", PyExc_Exception, NULL))) { 370 | goto error; 371 | } 372 | PyDict_SetItemString(dict, "Warning", pysqlite_Warning); 373 | 374 | /* Error subclasses */ 375 | 376 | if (!(pysqlite_InterfaceError = PyErr_NewException(MODULE_NAME ".InterfaceError", pysqlite_Error, NULL))) { 377 | goto error; 378 | } 379 | PyDict_SetItemString(dict, "InterfaceError", pysqlite_InterfaceError); 380 | 381 | if (!(pysqlite_DatabaseError = PyErr_NewException(MODULE_NAME ".DatabaseError", pysqlite_Error, NULL))) { 382 | goto error; 383 | } 384 | PyDict_SetItemString(dict, "DatabaseError", pysqlite_DatabaseError); 385 | 386 | /* pysqlite_DatabaseError subclasses */ 387 | 388 | if (!(pysqlite_InternalError = PyErr_NewException(MODULE_NAME ".InternalError", pysqlite_DatabaseError, NULL))) { 389 | goto error; 390 | } 391 | PyDict_SetItemString(dict, "InternalError", pysqlite_InternalError); 392 | 393 | if (!(pysqlite_OperationalError = PyErr_NewException(MODULE_NAME ".OperationalError", pysqlite_DatabaseError, NULL))) { 394 | goto error; 395 | } 396 | PyDict_SetItemString(dict, "OperationalError", pysqlite_OperationalError); 397 | 398 | if (!(pysqlite_ProgrammingError = PyErr_NewException(MODULE_NAME ".ProgrammingError", pysqlite_DatabaseError, NULL))) { 399 | goto error; 400 | } 401 | PyDict_SetItemString(dict, "ProgrammingError", pysqlite_ProgrammingError); 402 | 403 | if (!(pysqlite_IntegrityError = PyErr_NewException(MODULE_NAME ".IntegrityError", pysqlite_DatabaseError,NULL))) { 404 | goto error; 405 | } 406 | PyDict_SetItemString(dict, "IntegrityError", pysqlite_IntegrityError); 407 | 408 | if (!(pysqlite_DataError = PyErr_NewException(MODULE_NAME ".DataError", pysqlite_DatabaseError, NULL))) { 409 | goto error; 410 | } 411 | PyDict_SetItemString(dict, "DataError", pysqlite_DataError); 412 | 413 | if (!(pysqlite_NotSupportedError = PyErr_NewException(MODULE_NAME ".NotSupportedError", pysqlite_DatabaseError, NULL))) { 414 | goto error; 415 | } 416 | PyDict_SetItemString(dict, "NotSupportedError", pysqlite_NotSupportedError); 417 | 418 | /* In Python 2.x, setting Connection.text_factory to 419 | OptimizedUnicode caused Unicode objects to be returned for 420 | non-ASCII data and bytestrings to be returned for ASCII data. 421 | Now OptimizedUnicode is an alias for str, so it has no 422 | effect. */ 423 | Py_INCREF((PyObject*)&PyUnicode_Type); 424 | PyDict_SetItemString(dict, "OptimizedUnicode", (PyObject*)&PyUnicode_Type); 425 | 426 | /* Set integer constants */ 427 | for (i = 0; _int_constants[i].constant_name != 0; i++) { 428 | tmp_obj = PyLong_FromLong(_int_constants[i].constant_value); 429 | if (!tmp_obj) { 430 | goto error; 431 | } 432 | PyDict_SetItemString(dict, _int_constants[i].constant_name, tmp_obj); 433 | Py_DECREF(tmp_obj); 434 | } 435 | 436 | if (!(tmp_obj = PyUnicode_FromString(PYSQLITE_VERSION))) { 437 | goto error; 438 | } 439 | PyDict_SetItemString(dict, "version", tmp_obj); 440 | Py_DECREF(tmp_obj); 441 | 442 | if (!(tmp_obj = PyUnicode_FromString(sqlite3_libversion()))) { 443 | goto error; 444 | } 445 | PyDict_SetItemString(dict, "sqlite_version", tmp_obj); 446 | Py_DECREF(tmp_obj); 447 | 448 | /* initialize microprotocols layer */ 449 | pysqlite_microprotocols_init(dict); 450 | 451 | /* initialize the default converters */ 452 | converters_init(dict); 453 | 454 | _enable_callback_tracebacks = 0; 455 | 456 | pysqlite_BaseTypeAdapted = 0; 457 | 458 | /* Original comment from _bsddb.c in the Python core. This is also still 459 | * needed nowadays for Python 2.3/2.4. 460 | * 461 | * PyEval_InitThreads is called here due to a quirk in python 1.5 462 | * - 2.2.1 (at least) according to Russell Williamson : 463 | * The global interpreter lock is not initialized until the first 464 | * thread is created using thread.start_new_thread() or fork() is 465 | * called. that would cause the ALLOW_THREADS here to segfault due 466 | * to a null pointer reference if no threads or child processes 467 | * have been created. This works around that and is a no-op if 468 | * threads have already been initialized. 469 | * (see pybsddb-users mailing list post on 2002-08-07) 470 | */ 471 | #ifdef WITH_THREAD 472 | PyEval_InitThreads(); 473 | #endif 474 | 475 | error: 476 | if (PyErr_Occurred()) 477 | { 478 | PyErr_SetString(PyExc_ImportError, MODULE_NAME ": init failed"); 479 | Py_DECREF(module); 480 | module = NULL; 481 | } 482 | return module; 483 | } 484 | -------------------------------------------------------------------------------- /src/python3/module.h: -------------------------------------------------------------------------------- 1 | /* module.h - definitions for the module 2 | * 3 | * Copyright (C) 2004-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_MODULE_H 25 | #define PYSQLITE_MODULE_H 26 | #include "Python.h" 27 | 28 | #define PYSQLITE_VERSION "2.6.0" 29 | 30 | extern PyObject* pysqlite_Error; 31 | extern PyObject* pysqlite_Warning; 32 | extern PyObject* pysqlite_InterfaceError; 33 | extern PyObject* pysqlite_DatabaseError; 34 | extern PyObject* pysqlite_InternalError; 35 | extern PyObject* pysqlite_OperationalError; 36 | extern PyObject* pysqlite_ProgrammingError; 37 | extern PyObject* pysqlite_IntegrityError; 38 | extern PyObject* pysqlite_DataError; 39 | extern PyObject* pysqlite_NotSupportedError; 40 | 41 | /* the functions time.time() and time.sleep() */ 42 | extern PyObject* time_time; 43 | extern PyObject* time_sleep; 44 | 45 | /* A dictionary, mapping colum types (INTEGER, VARCHAR, etc.) to converter 46 | * functions, that convert the SQL value to the appropriate Python value. 47 | * The key is uppercase. 48 | */ 49 | extern PyObject* converters; 50 | 51 | extern int _enable_callback_tracebacks; 52 | extern int pysqlite_BaseTypeAdapted; 53 | 54 | #define PARSE_DECLTYPES 1 55 | #define PARSE_COLNAMES 2 56 | #endif 57 | -------------------------------------------------------------------------------- /src/python3/prepare_protocol.c: -------------------------------------------------------------------------------- 1 | /* prepare_protocol.c - the protocol for preparing values for SQLite 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "prepare_protocol.h" 25 | 26 | int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs) 27 | { 28 | return 0; 29 | } 30 | 31 | void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self) 32 | { 33 | Py_TYPE(self)->tp_free((PyObject*)self); 34 | } 35 | 36 | PyTypeObject pysqlite_PrepareProtocolType= { 37 | PyVarObject_HEAD_INIT(NULL, 0) 38 | MODULE_NAME ".PrepareProtocol", /* tp_name */ 39 | sizeof(pysqlite_PrepareProtocol), /* tp_basicsize */ 40 | 0, /* tp_itemsize */ 41 | (destructor)pysqlite_prepare_protocol_dealloc, /* tp_dealloc */ 42 | 0, /* tp_print */ 43 | 0, /* tp_getattr */ 44 | 0, /* tp_setattr */ 45 | 0, /* tp_reserved */ 46 | 0, /* tp_repr */ 47 | 0, /* tp_as_number */ 48 | 0, /* tp_as_sequence */ 49 | 0, /* tp_as_mapping */ 50 | 0, /* tp_hash */ 51 | 0, /* tp_call */ 52 | 0, /* tp_str */ 53 | 0, /* tp_getattro */ 54 | 0, /* tp_setattro */ 55 | 0, /* tp_as_buffer */ 56 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 57 | 0, /* tp_doc */ 58 | 0, /* tp_traverse */ 59 | 0, /* tp_clear */ 60 | 0, /* tp_richcompare */ 61 | 0, /* tp_weaklistoffset */ 62 | 0, /* tp_iter */ 63 | 0, /* tp_iternext */ 64 | 0, /* tp_methods */ 65 | 0, /* tp_members */ 66 | 0, /* tp_getset */ 67 | 0, /* tp_base */ 68 | 0, /* tp_dict */ 69 | 0, /* tp_descr_get */ 70 | 0, /* tp_descr_set */ 71 | 0, /* tp_dictoffset */ 72 | (initproc)pysqlite_prepare_protocol_init, /* tp_init */ 73 | 0, /* tp_alloc */ 74 | 0, /* tp_new */ 75 | 0 /* tp_free */ 76 | }; 77 | 78 | extern int pysqlite_prepare_protocol_setup_types(void) 79 | { 80 | pysqlite_PrepareProtocolType.tp_new = PyType_GenericNew; 81 | Py_SET_TYPE(&pysqlite_PrepareProtocolType, &PyType_Type); 82 | return PyType_Ready(&pysqlite_PrepareProtocolType); 83 | } 84 | -------------------------------------------------------------------------------- /src/python3/prepare_protocol.h: -------------------------------------------------------------------------------- 1 | /* prepare_protocol.h - the protocol for preparing values for SQLite 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_PREPARE_PROTOCOL_H 25 | #define PYSQLITE_PREPARE_PROTOCOL_H 26 | #include "Python.h" 27 | 28 | typedef struct 29 | { 30 | PyObject_HEAD 31 | } pysqlite_PrepareProtocol; 32 | 33 | extern PyTypeObject pysqlite_PrepareProtocolType; 34 | 35 | int pysqlite_prepare_protocol_init(pysqlite_PrepareProtocol* self, PyObject* args, PyObject* kwargs); 36 | void pysqlite_prepare_protocol_dealloc(pysqlite_PrepareProtocol* self); 37 | 38 | int pysqlite_prepare_protocol_setup_types(void); 39 | 40 | #define UNKNOWN (-1) 41 | #endif 42 | 43 | // In python >=3.11 Py_TYPE has changed https://docs.python.org/3.11/whatsnew/3.11.html 44 | #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) 45 | static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) 46 | { ob->ob_type = type; } 47 | #define Py_SET_TYPE(ob, type) _Py_SET_TYPE((PyObject*)(ob), type) 48 | #endif -------------------------------------------------------------------------------- /src/python3/row.c: -------------------------------------------------------------------------------- 1 | /* row.c - an enhanced tuple for database rows 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "row.h" 25 | #include "cursor.h" 26 | 27 | void pysqlite_row_dealloc(pysqlite_Row* self) 28 | { 29 | Py_XDECREF(self->data); 30 | Py_XDECREF(self->description); 31 | 32 | Py_TYPE(self)->tp_free((PyObject*)self); 33 | } 34 | 35 | static PyObject * 36 | pysqlite_row_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 37 | { 38 | pysqlite_Row *self; 39 | PyObject* data; 40 | pysqlite_Cursor* cursor; 41 | 42 | assert(type != NULL && type->tp_alloc != NULL); 43 | 44 | if (!_PyArg_NoKeywords("Row()", kwargs)) 45 | return NULL; 46 | if (!PyArg_ParseTuple(args, "OO", &cursor, &data)) 47 | return NULL; 48 | 49 | if (!PyObject_IsInstance((PyObject*)cursor, (PyObject*)&pysqlite_CursorType)) { 50 | PyErr_SetString(PyExc_TypeError, "instance of cursor required for first argument"); 51 | return NULL; 52 | } 53 | 54 | if (!PyTuple_Check(data)) { 55 | PyErr_SetString(PyExc_TypeError, "tuple required for second argument"); 56 | return NULL; 57 | } 58 | 59 | self = (pysqlite_Row *) type->tp_alloc(type, 0); 60 | if (self == NULL) 61 | return NULL; 62 | 63 | Py_INCREF(data); 64 | self->data = data; 65 | 66 | Py_INCREF(cursor->description); 67 | self->description = cursor->description; 68 | 69 | return (PyObject *) self; 70 | } 71 | 72 | PyObject* pysqlite_row_item(pysqlite_Row* self, Py_ssize_t idx) 73 | { 74 | PyObject* item = PyTuple_GetItem(self->data, idx); 75 | Py_XINCREF(item); 76 | return item; 77 | } 78 | 79 | PyObject* pysqlite_row_subscript(pysqlite_Row* self, PyObject* idx) 80 | { 81 | Py_ssize_t _idx; 82 | char* key; 83 | Py_ssize_t nitems, i; 84 | char* compare_key; 85 | 86 | char* p1; 87 | char* p2; 88 | 89 | PyObject* item; 90 | 91 | if (PyLong_Check(idx)) { 92 | _idx = PyNumber_AsSsize_t(idx, PyExc_IndexError); 93 | if (_idx == -1 && PyErr_Occurred()) 94 | return NULL; 95 | if (_idx < 0) 96 | _idx += PyTuple_GET_SIZE(self->data); 97 | item = PyTuple_GetItem(self->data, _idx); 98 | Py_XINCREF(item); 99 | return item; 100 | } else if (PyUnicode_Check(idx)) { 101 | key = _PyUnicode_AsString(idx); 102 | if (key == NULL) 103 | return NULL; 104 | 105 | nitems = PyTuple_Size(self->description); 106 | 107 | for (i = 0; i < nitems; i++) { 108 | PyObject *obj; 109 | obj = PyTuple_GET_ITEM(self->description, i); 110 | obj = PyTuple_GET_ITEM(obj, 0); 111 | compare_key = _PyUnicode_AsString(obj); 112 | if (!compare_key) { 113 | return NULL; 114 | } 115 | 116 | p1 = key; 117 | p2 = compare_key; 118 | 119 | while (1) { 120 | if ((*p1 == (char)0) || (*p2 == (char)0)) { 121 | break; 122 | } 123 | 124 | if ((*p1 | 0x20) != (*p2 | 0x20)) { 125 | break; 126 | } 127 | 128 | p1++; 129 | p2++; 130 | } 131 | 132 | if ((*p1 == (char)0) && (*p2 == (char)0)) { 133 | /* found item */ 134 | item = PyTuple_GetItem(self->data, i); 135 | Py_INCREF(item); 136 | return item; 137 | } 138 | 139 | } 140 | 141 | PyErr_SetString(PyExc_IndexError, "No item with that key"); 142 | return NULL; 143 | } 144 | else if (PySlice_Check(idx)) { 145 | PyErr_SetString(PyExc_ValueError, "slices not implemented, yet"); 146 | return NULL; 147 | } 148 | else { 149 | PyErr_SetString(PyExc_IndexError, "Index must be int or string"); 150 | return NULL; 151 | } 152 | } 153 | 154 | Py_ssize_t pysqlite_row_length(pysqlite_Row* self, PyObject* args, PyObject* kwargs) 155 | { 156 | return PyTuple_GET_SIZE(self->data); 157 | } 158 | 159 | PyObject* pysqlite_row_keys(pysqlite_Row* self, PyObject* args, PyObject* kwargs) 160 | { 161 | PyObject* list; 162 | int nitems, i; 163 | 164 | list = PyList_New(0); 165 | if (!list) { 166 | return NULL; 167 | } 168 | nitems = PyTuple_Size(self->description); 169 | 170 | for (i = 0; i < nitems; i++) { 171 | if (PyList_Append(list, PyTuple_GET_ITEM(PyTuple_GET_ITEM(self->description, i), 0)) != 0) { 172 | Py_DECREF(list); 173 | return NULL; 174 | } 175 | } 176 | 177 | return list; 178 | } 179 | 180 | static PyObject* pysqlite_iter(pysqlite_Row* self) 181 | { 182 | return PyObject_GetIter(self->data); 183 | } 184 | 185 | static Py_hash_t pysqlite_row_hash(pysqlite_Row *self) 186 | { 187 | return PyObject_Hash(self->description) ^ PyObject_Hash(self->data); 188 | } 189 | 190 | static PyObject* pysqlite_row_richcompare(pysqlite_Row *self, PyObject *_other, int opid) 191 | { 192 | if (opid != Py_EQ && opid != Py_NE) 193 | Py_RETURN_NOTIMPLEMENTED; 194 | 195 | if (PyType_IsSubtype(Py_TYPE(_other), &pysqlite_RowType)) { 196 | pysqlite_Row *other = (pysqlite_Row *)_other; 197 | PyObject *res = PyObject_RichCompare(self->description, other->description, opid); 198 | if ((opid == Py_EQ && res == Py_True) 199 | || (opid == Py_NE && res == Py_False)) { 200 | Py_DECREF(res); 201 | return PyObject_RichCompare(self->data, other->data, opid); 202 | } 203 | } 204 | Py_RETURN_NOTIMPLEMENTED; 205 | } 206 | 207 | PyMappingMethods pysqlite_row_as_mapping = { 208 | /* mp_length */ (lenfunc)pysqlite_row_length, 209 | /* mp_subscript */ (binaryfunc)pysqlite_row_subscript, 210 | /* mp_ass_subscript */ (objobjargproc)0, 211 | }; 212 | 213 | static PySequenceMethods pysqlite_row_as_sequence = { 214 | /* sq_length */ (lenfunc)pysqlite_row_length, 215 | /* sq_concat */ 0, 216 | /* sq_repeat */ 0, 217 | /* sq_item */ (ssizeargfunc)pysqlite_row_item, 218 | }; 219 | 220 | 221 | static PyMethodDef pysqlite_row_methods[] = { 222 | {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, 223 | PyDoc_STR("Returns the keys of the row.")}, 224 | {NULL, NULL} 225 | }; 226 | 227 | 228 | PyTypeObject pysqlite_RowType = { 229 | PyVarObject_HEAD_INIT(NULL, 0) 230 | MODULE_NAME ".Row", /* tp_name */ 231 | sizeof(pysqlite_Row), /* tp_basicsize */ 232 | 0, /* tp_itemsize */ 233 | (destructor)pysqlite_row_dealloc, /* tp_dealloc */ 234 | 0, /* tp_print */ 235 | 0, /* tp_getattr */ 236 | 0, /* tp_setattr */ 237 | 0, /* tp_reserved */ 238 | 0, /* tp_repr */ 239 | 0, /* tp_as_number */ 240 | 0, /* tp_as_sequence */ 241 | 0, /* tp_as_mapping */ 242 | (hashfunc)pysqlite_row_hash, /* tp_hash */ 243 | 0, /* tp_call */ 244 | 0, /* tp_str */ 245 | 0, /* tp_getattro */ 246 | 0, /* tp_setattro */ 247 | 0, /* tp_as_buffer */ 248 | Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */ 249 | 0, /* tp_doc */ 250 | (traverseproc)0, /* tp_traverse */ 251 | 0, /* tp_clear */ 252 | (richcmpfunc)pysqlite_row_richcompare, /* tp_richcompare */ 253 | 0, /* tp_weaklistoffset */ 254 | (getiterfunc)pysqlite_iter, /* tp_iter */ 255 | 0, /* tp_iternext */ 256 | pysqlite_row_methods, /* tp_methods */ 257 | 0, /* tp_members */ 258 | 0, /* tp_getset */ 259 | 0, /* tp_base */ 260 | 0, /* tp_dict */ 261 | 0, /* tp_descr_get */ 262 | 0, /* tp_descr_set */ 263 | 0, /* tp_dictoffset */ 264 | 0, /* tp_init */ 265 | 0, /* tp_alloc */ 266 | 0, /* tp_new */ 267 | 0 /* tp_free */ 268 | }; 269 | 270 | extern int pysqlite_row_setup_types(void) 271 | { 272 | pysqlite_RowType.tp_new = pysqlite_row_new; 273 | pysqlite_RowType.tp_as_mapping = &pysqlite_row_as_mapping; 274 | pysqlite_RowType.tp_as_sequence = &pysqlite_row_as_sequence; 275 | return PyType_Ready(&pysqlite_RowType); 276 | } 277 | -------------------------------------------------------------------------------- /src/python3/row.h: -------------------------------------------------------------------------------- 1 | /* row.h - an enhanced tuple for database rows 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_ROW_H 25 | #define PYSQLITE_ROW_H 26 | #include "Python.h" 27 | 28 | typedef struct _Row 29 | { 30 | PyObject_HEAD 31 | PyObject* data; 32 | PyObject* description; 33 | } pysqlite_Row; 34 | 35 | extern PyTypeObject pysqlite_RowType; 36 | 37 | int pysqlite_row_setup_types(void); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/python3/statement.c: -------------------------------------------------------------------------------- 1 | /* statement.c - the statement type 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "statement.h" 25 | #include "cursor.h" 26 | #include "connection.h" 27 | #include "microprotocols.h" 28 | #include "prepare_protocol.h" 29 | #include "util.h" 30 | 31 | /* prototypes */ 32 | static int pysqlite_check_remaining_sql(const char* tail); 33 | 34 | typedef enum { 35 | LINECOMMENT_1, 36 | IN_LINECOMMENT, 37 | COMMENTSTART_1, 38 | IN_COMMENT, 39 | COMMENTEND_1, 40 | NORMAL 41 | } parse_remaining_sql_state; 42 | 43 | typedef enum { 44 | TYPE_LONG, 45 | TYPE_FLOAT, 46 | TYPE_UNICODE, 47 | TYPE_BUFFER, 48 | TYPE_UNKNOWN 49 | } parameter_type; 50 | 51 | int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql) 52 | { 53 | const char* tail; 54 | int rc; 55 | const char* sql_cstr; 56 | Py_ssize_t sql_cstr_len; 57 | 58 | self->st = NULL; 59 | self->in_use = 0; 60 | 61 | sql_cstr = PyUnicode_AsUTF8AndSize(sql, &sql_cstr_len); 62 | if (sql_cstr == NULL) { 63 | rc = PYSQLITE_SQL_WRONG_TYPE; 64 | return rc; 65 | } 66 | if (strlen(sql_cstr) != (size_t)sql_cstr_len) { 67 | PyErr_SetString(PyExc_ValueError, "the query contains a null character"); 68 | return PYSQLITE_SQL_WRONG_TYPE; 69 | } 70 | 71 | self->in_weakreflist = NULL; 72 | Py_INCREF(sql); 73 | self->sql = sql; 74 | 75 | Py_BEGIN_ALLOW_THREADS 76 | rc = sqlite3_prepare(connection->db, 77 | sql_cstr, 78 | -1, 79 | &self->st, 80 | &tail); 81 | Py_END_ALLOW_THREADS 82 | 83 | self->db = connection->db; 84 | 85 | if (rc == SQLITE_OK && pysqlite_check_remaining_sql(tail)) { 86 | (void)sqlite3_finalize(self->st); 87 | self->st = NULL; 88 | rc = PYSQLITE_TOO_MUCH_SQL; 89 | } 90 | 91 | return rc; 92 | } 93 | 94 | int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter) 95 | { 96 | int rc = SQLITE_OK; 97 | const char* buffer; 98 | char* string; 99 | Py_ssize_t buflen; 100 | parameter_type paramtype; 101 | 102 | if (parameter == Py_None) { 103 | rc = sqlite3_bind_null(self->st, pos); 104 | goto final; 105 | } 106 | 107 | if (PyLong_CheckExact(parameter)) { 108 | paramtype = TYPE_LONG; 109 | } else if (PyFloat_CheckExact(parameter)) { 110 | paramtype = TYPE_FLOAT; 111 | } else if (PyUnicode_CheckExact(parameter)) { 112 | paramtype = TYPE_UNICODE; 113 | } else if (PyLong_Check(parameter)) { 114 | paramtype = TYPE_LONG; 115 | } else if (PyFloat_Check(parameter)) { 116 | paramtype = TYPE_FLOAT; 117 | } else if (PyUnicode_Check(parameter)) { 118 | paramtype = TYPE_UNICODE; 119 | } else if (PyObject_CheckBuffer(parameter)) { 120 | paramtype = TYPE_BUFFER; 121 | } else { 122 | paramtype = TYPE_UNKNOWN; 123 | } 124 | 125 | switch (paramtype) { 126 | case TYPE_LONG: { 127 | sqlite_int64 value = _pysqlite_long_as_int64(parameter); 128 | if (value == -1 && PyErr_Occurred()) 129 | rc = -1; 130 | else 131 | rc = sqlite3_bind_int64(self->st, pos, value); 132 | break; 133 | } 134 | case TYPE_FLOAT: 135 | rc = sqlite3_bind_double(self->st, pos, PyFloat_AsDouble(parameter)); 136 | break; 137 | case TYPE_UNICODE: 138 | string = PyUnicode_AsUTF8AndSize(parameter, &buflen); 139 | if (string == NULL) 140 | return -1; 141 | if (buflen > INT_MAX) { 142 | PyErr_SetString(PyExc_OverflowError, 143 | "string longer than INT_MAX bytes"); 144 | return -1; 145 | } 146 | rc = sqlite3_bind_text(self->st, pos, string, (int)buflen, SQLITE_TRANSIENT); 147 | break; 148 | case TYPE_BUFFER: 149 | if (PyObject_AsCharBuffer(parameter, &buffer, &buflen) != 0) { 150 | PyErr_SetString(PyExc_ValueError, "could not convert BLOB to buffer"); 151 | return -1; 152 | } 153 | if (buflen > INT_MAX) { 154 | PyErr_SetString(PyExc_OverflowError, 155 | "BLOB longer than INT_MAX bytes"); 156 | return -1; 157 | } 158 | rc = sqlite3_bind_blob(self->st, pos, buffer, buflen, SQLITE_TRANSIENT); 159 | break; 160 | case TYPE_UNKNOWN: 161 | rc = -1; 162 | } 163 | 164 | final: 165 | return rc; 166 | } 167 | 168 | /* returns 0 if the object is one of Python's internal ones that don't need to be adapted */ 169 | static int _need_adapt(PyObject* obj) 170 | { 171 | if (pysqlite_BaseTypeAdapted) { 172 | return 1; 173 | } 174 | 175 | if (PyLong_CheckExact(obj) || PyFloat_CheckExact(obj) 176 | || PyUnicode_CheckExact(obj) || PyByteArray_CheckExact(obj)) { 177 | return 0; 178 | } else { 179 | return 1; 180 | } 181 | } 182 | 183 | void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters) 184 | { 185 | PyObject* current_param; 186 | PyObject* adapted; 187 | const char* binding_name; 188 | int i; 189 | int rc; 190 | int num_params_needed; 191 | Py_ssize_t num_params; 192 | 193 | Py_BEGIN_ALLOW_THREADS 194 | num_params_needed = sqlite3_bind_parameter_count(self->st); 195 | Py_END_ALLOW_THREADS 196 | 197 | if (PyTuple_CheckExact(parameters) || PyList_CheckExact(parameters) || (!PyDict_Check(parameters) && PySequence_Check(parameters))) { 198 | /* parameters passed as sequence */ 199 | if (PyTuple_CheckExact(parameters)) { 200 | num_params = PyTuple_GET_SIZE(parameters); 201 | } else if (PyList_CheckExact(parameters)) { 202 | num_params = PyList_GET_SIZE(parameters); 203 | } else { 204 | num_params = PySequence_Size(parameters); 205 | } 206 | if (num_params != num_params_needed) { 207 | PyErr_Format(pysqlite_ProgrammingError, 208 | "Incorrect number of bindings supplied. The current " 209 | "statement uses %d, and there are %zd supplied.", 210 | num_params_needed, num_params); 211 | return; 212 | } 213 | for (i = 0; i < num_params; i++) { 214 | if (PyTuple_CheckExact(parameters)) { 215 | current_param = PyTuple_GET_ITEM(parameters, i); 216 | Py_XINCREF(current_param); 217 | } else if (PyList_CheckExact(parameters)) { 218 | current_param = PyList_GET_ITEM(parameters, i); 219 | Py_XINCREF(current_param); 220 | } else { 221 | current_param = PySequence_GetItem(parameters, i); 222 | } 223 | if (!current_param) { 224 | return; 225 | } 226 | 227 | if (!_need_adapt(current_param)) { 228 | adapted = current_param; 229 | } else { 230 | adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); 231 | if (adapted) { 232 | Py_DECREF(current_param); 233 | } else { 234 | PyErr_Clear(); 235 | adapted = current_param; 236 | } 237 | } 238 | 239 | rc = pysqlite_statement_bind_parameter(self, i + 1, adapted); 240 | Py_DECREF(adapted); 241 | 242 | if (rc != SQLITE_OK) { 243 | if (!PyErr_Occurred()) { 244 | PyErr_Format(pysqlite_InterfaceError, "Error binding parameter %d - probably unsupported type.", i); 245 | } 246 | return; 247 | } 248 | } 249 | } else if (PyDict_Check(parameters)) { 250 | /* parameters passed as dictionary */ 251 | for (i = 1; i <= num_params_needed; i++) { 252 | Py_BEGIN_ALLOW_THREADS 253 | binding_name = sqlite3_bind_parameter_name(self->st, i); 254 | Py_END_ALLOW_THREADS 255 | if (!binding_name) { 256 | PyErr_Format(pysqlite_ProgrammingError, "Binding %d has no name, but you supplied a dictionary (which has only names).", i); 257 | return; 258 | } 259 | 260 | binding_name++; /* skip first char (the colon) */ 261 | if (PyDict_CheckExact(parameters)) { 262 | current_param = PyDict_GetItemString(parameters, binding_name); 263 | Py_XINCREF(current_param); 264 | } else { 265 | current_param = PyMapping_GetItemString(parameters, binding_name); 266 | } 267 | if (!current_param) { 268 | PyErr_Format(pysqlite_ProgrammingError, "You did not supply a value for binding %d.", i); 269 | return; 270 | } 271 | 272 | if (!_need_adapt(current_param)) { 273 | adapted = current_param; 274 | } else { 275 | adapted = pysqlite_microprotocols_adapt(current_param, (PyObject*)&pysqlite_PrepareProtocolType, NULL); 276 | if (adapted) { 277 | Py_DECREF(current_param); 278 | } else { 279 | PyErr_Clear(); 280 | adapted = current_param; 281 | } 282 | } 283 | 284 | rc = pysqlite_statement_bind_parameter(self, i, adapted); 285 | Py_DECREF(adapted); 286 | 287 | if (rc != SQLITE_OK) { 288 | if (!PyErr_Occurred()) { 289 | PyErr_Format(pysqlite_InterfaceError, "Error binding parameter :%s - probably unsupported type.", binding_name); 290 | } 291 | return; 292 | } 293 | } 294 | } else { 295 | PyErr_SetString(PyExc_ValueError, "parameters are of unsupported type"); 296 | } 297 | } 298 | 299 | int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* params) 300 | { 301 | const char* tail; 302 | int rc; 303 | const char* sql_cstr; 304 | Py_ssize_t sql_len; 305 | sqlite3_stmt* new_st; 306 | 307 | sql_cstr = PyUnicode_AsUTF8AndSize(self->sql, &sql_len); 308 | if (sql_cstr == NULL) { 309 | rc = PYSQLITE_SQL_WRONG_TYPE; 310 | return rc; 311 | } 312 | 313 | Py_BEGIN_ALLOW_THREADS 314 | rc = sqlite3_prepare(self->db, 315 | sql_cstr, 316 | -1, 317 | &new_st, 318 | &tail); 319 | Py_END_ALLOW_THREADS 320 | 321 | if (rc == SQLITE_OK) { 322 | /* The efficient sqlite3_transfer_bindings is only available in SQLite 323 | * version 3.2.2 or later. For older SQLite releases, that might not 324 | * even define SQLITE_VERSION_NUMBER, we do it the manual way. 325 | */ 326 | #ifdef SQLITE_VERSION_NUMBER 327 | #if SQLITE_VERSION_NUMBER >= 3002002 328 | /* The check for the number of parameters is necessary to not trigger a 329 | * bug in certain SQLite versions (experienced in 3.2.8 and 3.3.4). */ 330 | if (sqlite3_bind_parameter_count(self->st) > 0) { 331 | (void)sqlite3_transfer_bindings(self->st, new_st); 332 | } 333 | #endif 334 | #else 335 | statement_bind_parameters(self, params); 336 | #endif 337 | 338 | (void)sqlite3_finalize(self->st); 339 | self->st = new_st; 340 | } 341 | 342 | return rc; 343 | } 344 | 345 | int pysqlite_statement_finalize(pysqlite_Statement* self) 346 | { 347 | int rc; 348 | 349 | rc = SQLITE_OK; 350 | if (self->st) { 351 | Py_BEGIN_ALLOW_THREADS 352 | rc = sqlite3_finalize(self->st); 353 | Py_END_ALLOW_THREADS 354 | self->st = NULL; 355 | } 356 | 357 | self->in_use = 0; 358 | 359 | return rc; 360 | } 361 | 362 | int pysqlite_statement_reset(pysqlite_Statement* self) 363 | { 364 | int rc; 365 | 366 | rc = SQLITE_OK; 367 | 368 | if (self->in_use && self->st) { 369 | Py_BEGIN_ALLOW_THREADS 370 | rc = sqlite3_reset(self->st); 371 | Py_END_ALLOW_THREADS 372 | 373 | if (rc == SQLITE_OK) { 374 | self->in_use = 0; 375 | } 376 | } 377 | 378 | return rc; 379 | } 380 | 381 | void pysqlite_statement_mark_dirty(pysqlite_Statement* self) 382 | { 383 | self->in_use = 1; 384 | } 385 | 386 | void pysqlite_statement_dealloc(pysqlite_Statement* self) 387 | { 388 | if (self->st) { 389 | Py_BEGIN_ALLOW_THREADS 390 | sqlite3_finalize(self->st); 391 | Py_END_ALLOW_THREADS 392 | } 393 | 394 | self->st = NULL; 395 | 396 | Py_XDECREF(self->sql); 397 | 398 | if (self->in_weakreflist != NULL) { 399 | PyObject_ClearWeakRefs((PyObject*)self); 400 | } 401 | 402 | Py_TYPE(self)->tp_free((PyObject*)self); 403 | } 404 | 405 | /* 406 | * Checks if there is anything left in an SQL string after SQLite compiled it. 407 | * This is used to check if somebody tried to execute more than one SQL command 408 | * with one execute()/executemany() command, which the DB-API and we don't 409 | * allow. 410 | * 411 | * Returns 1 if there is more left than should be. 0 if ok. 412 | */ 413 | static int pysqlite_check_remaining_sql(const char* tail) 414 | { 415 | const char* pos = tail; 416 | 417 | parse_remaining_sql_state state = NORMAL; 418 | 419 | for (;;) { 420 | switch (*pos) { 421 | case 0: 422 | return 0; 423 | case '-': 424 | if (state == NORMAL) { 425 | state = LINECOMMENT_1; 426 | } else if (state == LINECOMMENT_1) { 427 | state = IN_LINECOMMENT; 428 | } 429 | break; 430 | case ' ': 431 | case '\t': 432 | break; 433 | case '\n': 434 | case 13: 435 | if (state == IN_LINECOMMENT) { 436 | state = NORMAL; 437 | } 438 | break; 439 | case '/': 440 | if (state == NORMAL) { 441 | state = COMMENTSTART_1; 442 | } else if (state == COMMENTEND_1) { 443 | state = NORMAL; 444 | } else if (state == COMMENTSTART_1) { 445 | return 1; 446 | } 447 | break; 448 | case '*': 449 | if (state == NORMAL) { 450 | return 1; 451 | } else if (state == LINECOMMENT_1) { 452 | return 1; 453 | } else if (state == COMMENTSTART_1) { 454 | state = IN_COMMENT; 455 | } else if (state == IN_COMMENT) { 456 | state = COMMENTEND_1; 457 | } 458 | break; 459 | default: 460 | if (state == COMMENTEND_1) { 461 | state = IN_COMMENT; 462 | } else if (state == IN_LINECOMMENT) { 463 | } else if (state == IN_COMMENT) { 464 | } else { 465 | return 1; 466 | } 467 | } 468 | 469 | pos++; 470 | } 471 | 472 | return 0; 473 | } 474 | 475 | PyTypeObject pysqlite_StatementType = { 476 | PyVarObject_HEAD_INIT(NULL, 0) 477 | MODULE_NAME ".Statement", /* tp_name */ 478 | sizeof(pysqlite_Statement), /* tp_basicsize */ 479 | 0, /* tp_itemsize */ 480 | (destructor)pysqlite_statement_dealloc, /* tp_dealloc */ 481 | 0, /* tp_print */ 482 | 0, /* tp_getattr */ 483 | 0, /* tp_setattr */ 484 | 0, /* tp_reserved */ 485 | 0, /* tp_repr */ 486 | 0, /* tp_as_number */ 487 | 0, /* tp_as_sequence */ 488 | 0, /* tp_as_mapping */ 489 | 0, /* tp_hash */ 490 | 0, /* tp_call */ 491 | 0, /* tp_str */ 492 | 0, /* tp_getattro */ 493 | 0, /* tp_setattro */ 494 | 0, /* tp_as_buffer */ 495 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 496 | 0, /* tp_doc */ 497 | 0, /* tp_traverse */ 498 | 0, /* tp_clear */ 499 | 0, /* tp_richcompare */ 500 | offsetof(pysqlite_Statement, in_weakreflist), /* tp_weaklistoffset */ 501 | 0, /* tp_iter */ 502 | 0, /* tp_iternext */ 503 | 0, /* tp_methods */ 504 | 0, /* tp_members */ 505 | 0, /* tp_getset */ 506 | 0, /* tp_base */ 507 | 0, /* tp_dict */ 508 | 0, /* tp_descr_get */ 509 | 0, /* tp_descr_set */ 510 | 0, /* tp_dictoffset */ 511 | (initproc)0, /* tp_init */ 512 | 0, /* tp_alloc */ 513 | 0, /* tp_new */ 514 | 0 /* tp_free */ 515 | }; 516 | 517 | extern int pysqlite_statement_setup_types(void) 518 | { 519 | pysqlite_StatementType.tp_new = PyType_GenericNew; 520 | return PyType_Ready(&pysqlite_StatementType); 521 | } 522 | -------------------------------------------------------------------------------- /src/python3/statement.h: -------------------------------------------------------------------------------- 1 | /* statement.h - definitions for the statement type 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_STATEMENT_H 25 | #define PYSQLITE_STATEMENT_H 26 | #include "Python.h" 27 | 28 | #include "connection.h" 29 | #include "sqlcipher/sqlite3.h" 30 | 31 | #define PYSQLITE_TOO_MUCH_SQL (-100) 32 | #define PYSQLITE_SQL_WRONG_TYPE (-101) 33 | 34 | typedef struct 35 | { 36 | PyObject_HEAD 37 | sqlite3* db; 38 | sqlite3_stmt* st; 39 | PyObject* sql; 40 | int in_use; 41 | PyObject* in_weakreflist; /* List of weak references */ 42 | } pysqlite_Statement; 43 | 44 | extern PyTypeObject pysqlite_StatementType; 45 | 46 | int pysqlite_statement_create(pysqlite_Statement* self, pysqlite_Connection* connection, PyObject* sql); 47 | void pysqlite_statement_dealloc(pysqlite_Statement* self); 48 | 49 | int pysqlite_statement_bind_parameter(pysqlite_Statement* self, int pos, PyObject* parameter); 50 | void pysqlite_statement_bind_parameters(pysqlite_Statement* self, PyObject* parameters); 51 | 52 | int pysqlite_statement_recompile(pysqlite_Statement* self, PyObject* parameters); 53 | int pysqlite_statement_finalize(pysqlite_Statement* self); 54 | int pysqlite_statement_reset(pysqlite_Statement* self); 55 | void pysqlite_statement_mark_dirty(pysqlite_Statement* self); 56 | 57 | int pysqlite_statement_setup_types(void); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/python3/util.c: -------------------------------------------------------------------------------- 1 | /* util.c - various utility functions 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #include "module.h" 25 | #include "connection.h" 26 | 27 | int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection) 28 | { 29 | int rc; 30 | 31 | if (statement == NULL) { 32 | /* this is a workaround for SQLite 3.5 and later. it now apparently 33 | * returns NULL for "no-operation" statements */ 34 | rc = SQLITE_OK; 35 | } else { 36 | Py_BEGIN_ALLOW_THREADS 37 | rc = sqlite3_step(statement); 38 | Py_END_ALLOW_THREADS 39 | } 40 | 41 | return rc; 42 | } 43 | 44 | /** 45 | * Checks the SQLite error code and sets the appropriate DB-API exception. 46 | * Returns the error code (0 means no error occurred). 47 | */ 48 | int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st) 49 | { 50 | int errorcode; 51 | 52 | /* SQLite often doesn't report anything useful, unless you reset the statement first */ 53 | if (st != NULL) { 54 | (void)sqlite3_reset(st); 55 | } 56 | 57 | errorcode = sqlite3_errcode(db); 58 | 59 | switch (errorcode) 60 | { 61 | case SQLITE_OK: 62 | PyErr_Clear(); 63 | break; 64 | case SQLITE_INTERNAL: 65 | case SQLITE_NOTFOUND: 66 | PyErr_SetString(pysqlite_InternalError, sqlite3_errmsg(db)); 67 | break; 68 | case SQLITE_NOMEM: 69 | (void)PyErr_NoMemory(); 70 | break; 71 | case SQLITE_ERROR: 72 | case SQLITE_PERM: 73 | case SQLITE_ABORT: 74 | case SQLITE_BUSY: 75 | case SQLITE_LOCKED: 76 | case SQLITE_READONLY: 77 | case SQLITE_INTERRUPT: 78 | case SQLITE_IOERR: 79 | case SQLITE_FULL: 80 | case SQLITE_CANTOPEN: 81 | case SQLITE_PROTOCOL: 82 | case SQLITE_EMPTY: 83 | case SQLITE_SCHEMA: 84 | PyErr_SetString(pysqlite_OperationalError, sqlite3_errmsg(db)); 85 | break; 86 | case SQLITE_CORRUPT: 87 | PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db)); 88 | break; 89 | case SQLITE_TOOBIG: 90 | PyErr_SetString(pysqlite_DataError, sqlite3_errmsg(db)); 91 | break; 92 | case SQLITE_CONSTRAINT: 93 | case SQLITE_MISMATCH: 94 | PyErr_SetString(pysqlite_IntegrityError, sqlite3_errmsg(db)); 95 | break; 96 | case SQLITE_MISUSE: 97 | PyErr_SetString(pysqlite_ProgrammingError, sqlite3_errmsg(db)); 98 | break; 99 | default: 100 | PyErr_SetString(pysqlite_DatabaseError, sqlite3_errmsg(db)); 101 | break; 102 | } 103 | 104 | return errorcode; 105 | } 106 | 107 | #ifdef WORDS_BIGENDIAN 108 | # define IS_LITTLE_ENDIAN 0 109 | #else 110 | # define IS_LITTLE_ENDIAN 1 111 | #endif 112 | 113 | PyObject * 114 | _pysqlite_long_from_int64(sqlite_int64 value) 115 | { 116 | #ifdef HAVE_LONG_LONG 117 | # if SIZEOF_LONG_LONG < 8 118 | if (value > PY_LLONG_MAX || value < PY_LLONG_MIN) { 119 | return _PyLong_FromByteArray(&value, sizeof(value), 120 | IS_LITTLE_ENDIAN, 1 /* signed */); 121 | } 122 | # endif 123 | # if SIZEOF_LONG < SIZEOF_LONG_LONG 124 | if (value > LONG_MAX || value < LONG_MIN) 125 | return PyLong_FromLongLong(value); 126 | # endif 127 | #else 128 | # if SIZEOF_LONG < 8 129 | if (value > LONG_MAX || value < LONG_MIN) { 130 | return _PyLong_FromByteArray(&value, sizeof(value), 131 | IS_LITTLE_ENDIAN, 1 /* signed */); 132 | } 133 | # endif 134 | #endif 135 | return PyLong_FromLong(Py_SAFE_DOWNCAST(value, sqlite_int64, long)); 136 | } 137 | 138 | sqlite_int64 139 | _pysqlite_long_as_int64(PyObject * py_val) 140 | { 141 | int overflow; 142 | #ifdef HAVE_LONG_LONG 143 | PY_LONG_LONG value = PyLong_AsLongLongAndOverflow(py_val, &overflow); 144 | #else 145 | long value = PyLong_AsLongAndOverflow(py_val, &overflow); 146 | #endif 147 | if (value == -1 && PyErr_Occurred()) 148 | return -1; 149 | if (!overflow) { 150 | #ifdef HAVE_LONG_LONG 151 | # if SIZEOF_LONG_LONG > 8 152 | if (-0x8000000000000000LL <= value && value <= 0x7FFFFFFFFFFFFFFFLL) 153 | # endif 154 | #else 155 | # if SIZEOF_LONG > 8 156 | if (-0x8000000000000000L <= value && value <= 0x7FFFFFFFFFFFFFFFL) 157 | # endif 158 | #endif 159 | return value; 160 | } 161 | else if (sizeof(value) < sizeof(sqlite_int64)) { 162 | sqlite_int64 int64val; 163 | if (_PyLong_AsByteArray((PyLongObject *)py_val, 164 | (unsigned char *)&int64val, sizeof(int64val), 165 | IS_LITTLE_ENDIAN, 1 /* signed */) >= 0) { 166 | return int64val; 167 | } 168 | } 169 | PyErr_SetString(PyExc_OverflowError, 170 | "Python int too large to convert to SQLite INTEGER"); 171 | return -1; 172 | } 173 | -------------------------------------------------------------------------------- /src/python3/util.h: -------------------------------------------------------------------------------- 1 | /* util.h - various utility functions 2 | * 3 | * Copyright (C) 2005-2010 Gerhard Häring 4 | * 5 | * This file is part of pysqlite. 6 | * 7 | * This software is provided 'as-is', without any express or implied 8 | * warranty. In no event will the authors be held liable for any damages 9 | * arising from the use of this software. 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. If you use this software 17 | * in a product, an acknowledgment in the product documentation would be 18 | * appreciated but is not required. 19 | * 2. Altered source versions must be plainly marked as such, and must not be 20 | * misrepresented as being the original software. 21 | * 3. This notice may not be removed or altered from any source distribution. 22 | */ 23 | 24 | #ifndef PYSQLITE_UTIL_H 25 | #define PYSQLITE_UTIL_H 26 | #include "Python.h" 27 | #include "pythread.h" 28 | #include "sqlcipher/sqlite3.h" 29 | #include "connection.h" 30 | 31 | int pysqlite_step(sqlite3_stmt* statement, pysqlite_Connection* connection); 32 | 33 | /** 34 | * Checks the SQLite error code and sets the appropriate DB-API exception. 35 | * Returns the error code (0 means no error occurred). 36 | */ 37 | int _pysqlite_seterror(sqlite3* db, sqlite3_stmt* st); 38 | 39 | PyObject * _pysqlite_long_from_int64(sqlite_int64 value); 40 | sqlite_int64 _pysqlite_long_as_int64(PyObject * value); 41 | 42 | #endif 43 | --------------------------------------------------------------------------------