├── .github └── workflows │ └── pypi.yml ├── LICENSE.TXT ├── MANIFEST.in ├── PKG-INFO ├── README.md ├── docs ├── .buildinfo ├── Makefile ├── _sources │ ├── changelog.txt │ ├── differences-from-kdb.txt │ ├── getting-started.txt │ ├── index.txt │ ├── license.txt │ ├── python-db-api-compliance.txt │ ├── reference.txt │ ├── requirements.txt │ └── usage-guide.txt ├── _static │ ├── ajax-loader.gif │ ├── basic.css │ ├── comment-bright.png │ ├── comment-close.png │ ├── comment.png │ ├── dialog-note.png │ ├── dialog-seealso.png │ ├── dialog-topic.png │ ├── dialog-warning.png │ ├── doctools.js │ ├── documentation_options.js │ ├── down-pressed.png │ ├── down.png │ ├── epub.css │ ├── file.png │ ├── footerbg.png │ ├── headerbg.png │ ├── ie6.css │ ├── interbasetheme.css │ ├── jquery.js │ ├── language_data.js │ ├── middlebg.png │ ├── minus.png │ ├── plus.png │ ├── pygments.css │ ├── searchtools.js │ ├── sphinx_highlight.js │ ├── transparent.gif │ ├── underscore.js │ ├── up-pressed.png │ ├── up.png │ └── websupport.js ├── changelog.html ├── differences-from-kdb.html ├── genindex.html ├── getting-started.html ├── index.html ├── license.html ├── listinv.py ├── make.bat ├── objects.inv ├── py-modindex.html ├── python-db-api-compliance.html ├── reference.html ├── requirements.html ├── search.html ├── searchindex.js ├── source │ ├── conf.py │ └── index.rst └── usage-guide.html ├── interbase ├── __init__.py ├── blr.py ├── ibase.py ├── ibcore.py ├── schema.py ├── services.py ├── test │ ├── README.md │ ├── __init__.py │ ├── constants.py │ ├── core.py │ ├── files │ │ ├── cert │ │ │ ├── 3b307515.0 │ │ │ └── ibserverCAfile.pem │ │ ├── create-test-db-dialect-1.sh │ │ ├── create-test-db-dialect-1.sql │ │ ├── create-test-db.bat │ │ ├── create-test-db.sh │ │ ├── create-test-db.sql │ │ ├── ibserverCAfile.pem │ │ └── isql.sh │ ├── test_arrays.py │ ├── test_bugs.py │ ├── test_change_views.py │ ├── test_charset_conversion.py │ ├── test_connection.py │ ├── test_create.py │ ├── test_cursor.py │ ├── test_dbapi20.py │ ├── test_distributed_transaction.py │ ├── test_encryption.py │ ├── test_events.py │ ├── test_insert_data.py │ ├── test_prepared_statement.py │ ├── test_schema.py │ ├── test_services.py │ ├── test_stored_proc.py │ ├── test_stream_blobs.py │ └── test_transaction.py └── utils.py ├── pyproject.toml ├── setup.cfg ├── setup.py └── sphinx ├── Makefile ├── changelog.txt ├── conf.py ├── getting-started.txt ├── index.txt ├── interbasetheme ├── layout.html ├── static │ ├── dialog-note.png │ ├── dialog-seealso.png │ ├── dialog-topic.png │ ├── dialog-warning.png │ ├── epub.css │ ├── footerbg.png │ ├── headerbg.png │ ├── ie6.css │ ├── interbasetheme.css_t │ ├── middlebg.png │ └── transparent.gif └── theme.conf ├── license.txt ├── python-db-api-compliance.txt ├── reference.txt ├── requirements.txt └── usage-guide.txt /.github/workflows/pypi.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | 6 | jobs: 7 | build_wheel: 8 | name: Build Python 3 wheel 9 | runs-on: ${{ matrix.os }} 10 | strategy: 11 | matrix: 12 | python: ['3.10'] 13 | include: 14 | - os: ubuntu-20.04 15 | arch: "x86_64" 16 | steps: 17 | - name: Check out repository 18 | uses: actions/checkout@v3 19 | with: 20 | fetch-depth: 0 21 | 22 | - name: Set up Python ${{ matrix.python }} 23 | uses: actions/setup-python@v3 24 | with: 25 | python-version: ${{ matrix.python }} 26 | 27 | - name: Build wheel 28 | run: | 29 | python -m pip install build 30 | python -m build --wheel . 31 | 32 | - name: Save sdist 33 | uses: actions/upload-artifact@v4 34 | with: 35 | name: artifact 36 | path: dist/*.whl 37 | if-no-files-found: error 38 | 39 | upload_pypi_test: 40 | name: Upload to PyPI test 41 | needs: [build_wheel] 42 | runs-on: ubuntu-latest 43 | environment: 44 | name: pypi 45 | url: https://test.pypi.org/p/interbasepython 46 | permissions: 47 | id-token: write 48 | if: github.ref == 'refs/heads/main' 49 | steps: 50 | - uses: actions/download-artifact@v4 51 | with: 52 | name: artifact 53 | path: dist 54 | 55 | - name: Publish package to TestPyPI 56 | uses: pypa/gh-action-pypi-publish@release/v1 57 | with: 58 | repository_url: https://test.pypi.org/legacy/ 59 | 60 | upload_pypi: 61 | name: Upload to PyPI 62 | needs: [build_wheel] 63 | runs-on: ubuntu-latest 64 | environment: 65 | name: pypi 66 | url: https://pypi.org/p/interbasepython 67 | permissions: 68 | id-token: write 69 | if: startsWith(github.ref, 'refs/tags/v') 70 | steps: 71 | - uses: actions/download-artifact@v4 72 | with: 73 | name: artifact 74 | path: dist 75 | 76 | - name: Publish package to PyPI 77 | uses: pypa/gh-action-pypi-publish@release/v1 78 | 79 | upload_gh_pages: 80 | name: Deploy to GitHub Pages 81 | needs: [upload_pypi] 82 | runs-on: windows-latest 83 | if: startsWith(github.ref, 'refs/tags/v') 84 | steps: 85 | - name: Check out repository 86 | uses: actions/checkout@v3 87 | with: 88 | fetch-depth: 0 89 | - name: Publish docs 90 | uses: peaceiris/actions-gh-pages@v3 91 | with: 92 | publish_branch: gh-pages 93 | github_token: ${{ secrets.GITHUB_TOKEN }} 94 | publish_dir: docs/ 95 | force_orphan: true 96 | -------------------------------------------------------------------------------- /LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ======= 2 | LICENSE 3 | ======= 4 | 5 | The following contributors hold Copyright (c) over their respective portions 6 | of code and documentation: 7 | 8 | Contributors: 9 | 10 | [The main portion of initial code (~95%)] 11 | Pavel Cisar 12 | 13 | [Author of blog post with instructions for converting driver to work with InterBase ] 14 | Gabe Goldfield 15 | 16 | [Initial trace API & nbackup support; Python 3 support] 17 | Philippe Makowski 18 | 19 | Some code in inital version is Python code from KInterbasDB 3.3.0. 20 | As it's very hard to find out who exactly was the original author of used code, 21 | here is the full list of KInterbasDB contributors: 22 | 23 | [Author of original version; maintained through version 2.0:] 24 | 25 | 1998-2001 [alex] Alexander Kuznetsov 26 | 27 | [Author of ~90% of current code, most of current documentation; maintained through version 3.3:] 28 | 29 | 2002-2007 [dsr] David S. Rushby 30 | 31 | [Finishing touch to v3.3; New Documentation; Current maintainer:] 32 | 33 | 2008-2011 [paci] Pavel Cisar 34 | 35 | [Significant Contributors:] 36 | 37 | 2001-2002 [maz] Marek Isalski 38 | 39 | Marek made important first steps in removing the limitations of version 2.0 40 | in preparation for version 3.0. 41 | 42 | 2001 [eac] Evgeny A. Cherkashin 43 | 44 | Evgeny wrote the first version of the distutils build script, 45 | which was included in a 2.x point release. 46 | 47 | 2001-2002 [janez] Janez Jere 48 | 49 | Janez contributed several bugfixes, including fixes for the date and time 50 | parameter conversion code in preparation for version 3.0. 51 | 52 | Permission to use, copy, modify, and distribute this software and its documentation 53 | for any purpose and without fee or royalty is hereby granted, provided that the above 54 | copyright notice appears in all copies and that both the copyright notice and 55 | this permission notice appear in supporting documentation or portions thereof, 56 | including modifications, that you make. 57 | 58 | The authors disclaim all warranties with regard to this software, including all 59 | implied warranties of merchantability and fitness. In no event shall any author 60 | be liable for any special, indirect or consequential damages or any damages whatsoever 61 | resulting from loss of use, data or profits, whether in an action of contract, 62 | negligence or other tortious action, arising out of or in connection with the use 63 | or performance of this software. 64 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE.TXT 2 | include docs/* 3 | -------------------------------------------------------------------------------- /PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.1 2 | Name: interbase 3 | Version: 1.5.0 4 | Summary: InterBase RDBMS bindings for Python. 5 | Home-page: https://github.com/Embarcadero/InterBasePython 6 | Author: 7 | Author-email: 8 | License: BSD 9 | Description: interbase package is a set of InterBase RDBMS bindings for python. 10 | It works on Python 3.x. 11 | 12 | Keywords: InterBase 13 | Platform: UNKNOWN 14 | Classifier: Development Status :: 5 - Production/Stable 15 | Classifier: License :: OSI Approved :: BSD License 16 | Classifier: Operating System :: OS Independent 17 | Classifier: Programming Language :: Python 18 | Classifier: Topic :: Database 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # InterBase Driver for Python 2 | 3 | InterBase 4 | 5 | > A powerful, [PEP-249-compliant](https://peps.python.org/pep-0249/) Python driver for **InterBase**, supporting both 32-bit and 64-bit. 6 | 7 | The **InterBase Driver for Python** is based on the [FDB driver](http://www.firebirdsql.org/en/devel-python-driver/) and provides access to the [InterBase](https://interbase.com/) RDBMS using a robust and flexible Python interface. This package supports the **Python Database API 2.0** standard (PEP-249) while offering extended access to the native InterBase API. 8 | 9 | 📚 [InterBase Documentation](https://docwiki.embarcadero.com/InterBase/2020/en/Main_Page) 10 | 🔗 [GitHub Source Code](https://github.com/Embarcadero/InterBasePython) 11 | 12 | --- 13 | 14 | ## ✨ Features 15 | 16 | - PEP-249 compliance 17 | - Full Unicode and character set support 18 | - Native API access 19 | - Multiple independent transactions per connection 20 | - Distributed transaction support 21 | - Automatic conversion of textual data 22 | - Prepared statement support 23 | 24 | --- 25 | 26 | ## 📦 Installation 27 | 28 | > Requires Python 3.x (32-bit or 64-bit version to match InterBase client). 29 | 30 | Install via PyPI: 31 | ```bash 32 | pip install interbase 33 | ``` 34 | 35 | Or install from the GitHub repository: 36 | ```bash 37 | pip install git+https://github.com/Embarcadero/InterBasePython.git 38 | # or via SSH: 39 | pip install git+ssh://git@github.com/Embarcadero/InterBasePython.git 40 | ``` 41 | 42 | --- 43 | 44 | ## 🧪 Setting Up a Test Database 45 | 46 | ```bash 47 | cd test/files 48 | isql -i create-test-db.sql 49 | ``` 50 | 51 | --- 52 | 53 | ## 🔌 Sample Usage 54 | 55 | ### Basic Connection 56 | ```python 57 | import interbase 58 | 59 | con = interbase.connect( 60 | host=IBTEST_HOST, # Hostname or IP address of the InterBase server 61 | database=IBTEST_DB_PATH, # Path to the database file on the server 62 | user=IBTEST_USER, # Username for authentication 63 | password=IBTEST_PASSWORD, # Password for authentication 64 | sql_dialect=IBTEST_SQL_DIALECT, # SQL dialect to use (usually 1 or 3) 65 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, # Enable SSL if a public server key is provided 66 | server_public_file=IBTEST_SERVER_PUBLIC_FILE # Path to the server's public SSL key file (if SSL is enabled) 67 | ) 68 | ``` 69 | 70 | ### Executing a Query 71 | ```python 72 | cur = con.cursor() 73 | cur.execute("SELECT * FROM employees") 74 | for row in cur: 75 | print(row) 76 | ``` 77 | 78 | ### Using Parameters 79 | ```python 80 | cur.execute("INSERT INTO employees(name, age) VALUES (?, ?)", ("John Doe", 34)) 81 | con.commit() 82 | ``` 83 | 84 | ### Handling Transactions 85 | 86 | #### Manual Transaction Control 87 | ```python 88 | transaction = con.main_transaction 89 | transaction.begin() 90 | 91 | cursor = transaction.cursor() 92 | cursor.execute("INSERT INTO t (c1) VALUES (1)") 93 | transaction.commit() 94 | ``` 95 | 96 | #### Using a Context Manager 97 | ```python 98 | import interbase 99 | 100 | with interbase.TransactionContext(con) as tr: 101 | cursor = tr.cursor() 102 | cursor.execute("INSERT INTO t (c1) VALUES (1)") 103 | # The transaction is automatically committed when the block ends. 104 | ``` 105 | 106 | --- 107 | 108 | ## 🧰 More Examples 109 | Explore the `test` folder in the [GitHub Repository](https://github.com/Embarcadero/InterBasePython) for full coverage of features, including: 110 | 111 | - Working with BLOBs 112 | - Using metadata APIs 113 | - Working with stored procedures 114 | - SSL support 115 | - Error handling 116 | 117 | --- 118 | 119 | ## 🤝 Contributing 120 | Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change. 121 | 122 | --- 123 | 124 | ## 📜 License 125 | This project is licensed under the Embarcadero license terms. 126 | 127 | --- 128 | 129 | > 🔗 Stay up to date with the latest changes and enhancements to InterBase by following the official [Embarcadero Blog](https://blogs.embarcadero.com/). 130 | -------------------------------------------------------------------------------- /docs/.buildinfo: -------------------------------------------------------------------------------- 1 | # Sphinx build info version 1 2 | # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. 3 | config: 6a2af01995ecb4a6bfe4433df65e503d 4 | tags: 645f666f9bcd5a90fca523b33c5a78b7 5 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | 9 | # Internal variables. 10 | PAPEROPT_a4 = -D latex_paper_size=a4 11 | PAPEROPT_letter = -D latex_paper_size=letter 12 | ALLSPHINXOPTS = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 13 | 14 | .PHONY: help clean html web pickle htmlhelp latex changes linkcheck 15 | 16 | help: 17 | @echo "Please use \`make ' where is one of" 18 | @echo " html to make standalone HTML files" 19 | @echo " pickle to make pickle files" 20 | @echo " json to make JSON files" 21 | @echo " htmlhelp to make HTML files and a HTML help project" 22 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 23 | @echo " changes to make an overview over all changed/added/deprecated items" 24 | @echo " linkcheck to check all external links for integrity" 25 | 26 | clean: 27 | -rm -rf .build/* 28 | 29 | html: 30 | mkdir -p .build/html .build/doctrees 31 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) ../docs 32 | @echo 33 | @echo "Build finished. The HTML pages are in ../docs." 34 | 35 | pickle: 36 | mkdir -p .build/pickle .build/doctrees 37 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle 38 | @echo 39 | @echo "Build finished; now you can process the pickle files." 40 | 41 | web: pickle 42 | 43 | json: 44 | mkdir -p .build/json .build/doctrees 45 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) .build/json 46 | @echo 47 | @echo "Build finished; now you can process the JSON files." 48 | 49 | htmlhelp: 50 | mkdir -p .build/htmlhelp .build/doctrees 51 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp 52 | @echo 53 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 54 | ".hhp project file in .build/htmlhelp." 55 | 56 | latex: 57 | mkdir -p .build/latex .build/doctrees 58 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex 59 | @echo 60 | @echo "Build finished; the LaTeX files are in .build/latex." 61 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 62 | "run these through (pdf)latex." 63 | 64 | changes: 65 | mkdir -p .build/changes .build/doctrees 66 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes 67 | @echo 68 | @echo "The overview file is in .build/changes." 69 | 70 | linkcheck: 71 | mkdir -p .build/linkcheck .build/doctrees 72 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck 73 | @echo 74 | @echo "Link check complete; look for any errors in the above output " \ 75 | "or in .build/linkcheck/output.txt." -------------------------------------------------------------------------------- /docs/_sources/changelog.txt: -------------------------------------------------------------------------------- 1 | ######### 2 | Changelog 3 | ######### 4 | 5 | * `Version 1.5.0`_ (15.3.2023) 6 | 7 | Version 1.5.0 8 | ============= 9 | 10 | -------------------------------------------------------------------------------- /docs/_sources/differences-from-kdb.txt: -------------------------------------------------------------------------------- 1 | ============================ 2 | Differences from KInterbasDB 3 | ============================ 4 | 5 | No need for initialization 6 | ========================== 7 | 8 | IDB doesn't support various configurations of automatic type translations like 9 | KDB, so it's no longer necessary to initialize the driver before any feature is 10 | used. 11 | 12 | Distributed transactions 13 | ======================== 14 | 15 | Support for :ref:`Distributed Transactions ` works slightly 16 | differently than in KDB. IDB uses :class:`~idbIDB.ConnectionGroup` class like KDB with the same 17 | interface, but DT is not bound to main transaction of individual connections managed by group. 18 | That means that :class:`~idbIDB.Cursor` instances obtained from :class:`~idbIDB.Connection` don't work in 19 | DT if connection is part of ConnectionGroup, but work normally in connection context. 20 | To get Cursor for specific connection that works in DT, use :meth:`idbIDB.ConnectionGroup.cursor()` 21 | method and pass the connection as parameter. We believe that this arrangement is more 22 | logical and flexible than KDB's way. 23 | 24 | Transaction context for cursor objects depends on how cursor is obtained/created: 25 | 26 | a) :meth:`idb.Connection.cursor()` - Works in context of "main" transaction for connection. 27 | b) :meth:`idb.Transaction.cursor()` - Works in context of this transaction. 28 | c) :meth:`idb.ConnectionGroup.cursor()` - Works in context of Distributed Transaction 29 | 30 | Stream BLOBs 31 | ============ 32 | 33 | InterBase supports two types of BLOBs, stream and segmented. The database stores 34 | segmented BLOBs in chunks. Each chunk starts with a two byte length indicator 35 | followed by however many bytes of data were passed as a segment. Stream BLOBs 36 | are stored as a continuous array of data bytes with no length indicators included. 37 | Both types of BLOBs could be accessed by the same API functions, but only stream 38 | BLOBs support seek operation (via `isc_seek_blob function`). 39 | 40 | IDB implements stream BLOBs as file-like objects. On input, you can simply pass 41 | any file-like object (only 'read' method is required) as parameter value for BLOB 42 | column. For example: 43 | 44 | .. code-block:: python 45 | 46 | f = open('filename.ext', 'rb') 47 | cur.execute('insert into T (MyBLOB) values (?)',[f]) 48 | f.close() 49 | 50 | On output, stream BLOBs are represented by BlobReader instances on request. To 51 | request streamed access to BLOB, you have to use prepared statement for your query 52 | and call its `set_stream_blob(column_name)` method. Stream access is not allowed 53 | for cursors because cursors cache prepared statements internally, which would 54 | lead to dangerous situations (BlobReader life-time management) and anomalies 55 | (stream access when it's not required). Example: 56 | 57 | .. code-block:: python 58 | 59 | p = cursor.prep('select first 1 MyBLOB from T') 60 | p.set_stream_blob('MyBLOB') 61 | cur.execute(p) 62 | row = cur.fetchone() 63 | blob_reader = row[1] 64 | print blob_reader.readlines() 65 | blob_reader.close() 66 | 67 | Whenever you use stream access to BLOB, IDB opens or creates the underlying BLOB 68 | value as stream one. On input it means that true stream BLOB is created in database, 69 | but on output it depends on how BLOB value was actually created. If BLOB was 70 | created as stream one, you can use the seek method of BlobReader, but if it was 71 | created as regular BLOB, any call to seek will raise an error:: 72 | 73 | SQLCODE: -685 74 | - invalid ARRAY or BLOB operation 75 | - invalid BLOB type for operation 76 | 77 | You can read BLOBs created as stream ones as fully materialized, and regular ones 78 | in stream mode (without seek) without any problems, and that same apply for 79 | input - you can create values in the same column as stream or regular ones 80 | interchangeably. From your point of view, stream BLOBs are just different 81 | interface to BLOB values, with single exception - `BlobReader.seek()` will throw 82 | an exception if you'd call it on BLOB value that was not created as stream BLOB. 83 | 84 | To work with stream BLOBs, you don't need to use `cursor.set_type_trans_in/out` 85 | methods like in KDB, i.e. calls to: 86 | 87 | .. code-block:: python 88 | 89 | cur.set_type_trans_in ({'BLOB': {'mode': 'stream'}}) 90 | cur.set_type_trans_out({'BLOB': {'mode': 'stream'}}) 91 | 92 | To write (create) stream BLOB value, simply pass file-like object as parameter 93 | to your INSERT/UPDATE statements where BLOB value is expected. To read BLOB 94 | value as stream, use prepared statement and register interest to get BlobReader 95 | instead fully materialized value via set_stream_blob() calls for each BLOB value 96 | (column name) you want to get this way. 97 | 98 | :class:`~idb.BlobReader` supports iteration protocol, and read(), readline(), readlines(), 99 | seek(), tell(), flush() (as noop) and close() methods. It does NOT support chunks() 100 | method of KInterbasDB.BlobReader. 101 | 102 | It is not strictly necessary to close BlobReader instances explicitly. 103 | A BlobReader object will be automatically closed by its __del__ method when it 104 | goes out of scope, or when its Connection, PreparedStatement closes, 105 | whichever comes first. However, it is always a better idea to close resources 106 | explicitly (via try...finally) than to rely on artifacts of the Python 107 | implementation. You will also encounter errors if BLOB value was deleted from 108 | database before BlobReader is closed, so the odds that this may happen are higher 109 | if you do not close it explicitly. 110 | 111 | Services API 112 | ============ 113 | 114 | Support for InterBase Services was :ref:`completelly reworked ` in IDB. 115 | -------------------------------------------------------------------------------- /docs/_sources/index.txt: -------------------------------------------------------------------------------- 1 | .. Interbase documentation master file, created by sphinx-quickstart on Wed Jan 7 12:29:48 2009. 2 | You can adapt this file completely to your liking, but it should at least 3 | contain the root `toctree` directive. 4 | 5 | ##################################### 6 | Welcome to Interbase's documentation! 7 | ##################################### 8 | 9 | Interbase is a `Python `__ library package that 10 | implements `Python Database API 2.0`-compliant support for the relational 11 | database `InterBase® `__. 12 | In addition to the minimal feature set of the standard Python DB API, 13 | Interbase also exposes nearly the entire native client API of the database engine. 14 | 15 | Interbase is free -- covered by a permissive BSD-style `license 16 | `__ that both commercial and noncommercial users should 17 | find agreeable. 18 | 19 | This documentation set is not a tutorial on Python, SQL, or InterBase; 20 | rather, it is a topical presentation of Interbase's feature set, 21 | with example code to demonstrate basic usage patterns. For detailed 22 | information about InterBase features, see the `InterBase documentation 23 | `. 24 | 25 | Documentation Contents: 26 | *********************** 27 | 28 | .. toctree:: 29 | :maxdepth: 2 30 | 31 | getting-started 32 | usage-guide 33 | python-db-api-compliance 34 | reference 35 | 36 | changelog 37 | license 38 | 39 | 40 | Indices and tables 41 | ****************** 42 | 43 | * :ref:`genindex` 44 | * :ref:`modindex` 45 | * :ref:`search` 46 | 47 | -------------------------------------------------------------------------------- /docs/_sources/license.txt: -------------------------------------------------------------------------------- 1 | .. include:: ../LICENSE.TXT 2 | 3 | -------------------------------------------------------------------------------- /docs/_sources/requirements.txt: -------------------------------------------------------------------------------- 1 | idb 2 | -------------------------------------------------------------------------------- /docs/_static/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/ajax-loader.gif -------------------------------------------------------------------------------- /docs/_static/comment-bright.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/comment-bright.png -------------------------------------------------------------------------------- /docs/_static/comment-close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/comment-close.png -------------------------------------------------------------------------------- /docs/_static/comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/comment.png -------------------------------------------------------------------------------- /docs/_static/dialog-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/dialog-note.png -------------------------------------------------------------------------------- /docs/_static/dialog-seealso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/dialog-seealso.png -------------------------------------------------------------------------------- /docs/_static/dialog-topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/dialog-topic.png -------------------------------------------------------------------------------- /docs/_static/dialog-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/dialog-warning.png -------------------------------------------------------------------------------- /docs/_static/doctools.js: -------------------------------------------------------------------------------- 1 | /* 2 | * doctools.js 3 | * ~~~~~~~~~~~ 4 | * 5 | * Base JavaScript utilities for all Sphinx HTML documentation. 6 | * 7 | * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | "use strict"; 12 | 13 | const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ 14 | "TEXTAREA", 15 | "INPUT", 16 | "SELECT", 17 | "BUTTON", 18 | ]); 19 | 20 | const _ready = (callback) => { 21 | if (document.readyState !== "loading") { 22 | callback(); 23 | } else { 24 | document.addEventListener("DOMContentLoaded", callback); 25 | } 26 | }; 27 | 28 | /** 29 | * Small JavaScript module for the documentation. 30 | */ 31 | const Documentation = { 32 | init: () => { 33 | Documentation.initDomainIndexTable(); 34 | Documentation.initOnKeyListeners(); 35 | }, 36 | 37 | /** 38 | * i18n support 39 | */ 40 | TRANSLATIONS: {}, 41 | PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), 42 | LOCALE: "unknown", 43 | 44 | // gettext and ngettext don't access this so that the functions 45 | // can safely bound to a different name (_ = Documentation.gettext) 46 | gettext: (string) => { 47 | const translated = Documentation.TRANSLATIONS[string]; 48 | switch (typeof translated) { 49 | case "undefined": 50 | return string; // no translation 51 | case "string": 52 | return translated; // translation exists 53 | default: 54 | return translated[0]; // (singular, plural) translation tuple exists 55 | } 56 | }, 57 | 58 | ngettext: (singular, plural, n) => { 59 | const translated = Documentation.TRANSLATIONS[singular]; 60 | if (typeof translated !== "undefined") 61 | return translated[Documentation.PLURAL_EXPR(n)]; 62 | return n === 1 ? singular : plural; 63 | }, 64 | 65 | addTranslations: (catalog) => { 66 | Object.assign(Documentation.TRANSLATIONS, catalog.messages); 67 | Documentation.PLURAL_EXPR = new Function( 68 | "n", 69 | `return (${catalog.plural_expr})` 70 | ); 71 | Documentation.LOCALE = catalog.locale; 72 | }, 73 | 74 | /** 75 | * helper function to focus on search bar 76 | */ 77 | focusSearchBar: () => { 78 | document.querySelectorAll("input[name=q]")[0]?.focus(); 79 | }, 80 | 81 | /** 82 | * Initialise the domain index toggle buttons 83 | */ 84 | initDomainIndexTable: () => { 85 | const toggler = (el) => { 86 | const idNumber = el.id.substr(7); 87 | const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); 88 | if (el.src.substr(-9) === "minus.png") { 89 | el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; 90 | toggledRows.forEach((el) => (el.style.display = "none")); 91 | } else { 92 | el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; 93 | toggledRows.forEach((el) => (el.style.display = "")); 94 | } 95 | }; 96 | 97 | const togglerElements = document.querySelectorAll("img.toggler"); 98 | togglerElements.forEach((el) => 99 | el.addEventListener("click", (event) => toggler(event.currentTarget)) 100 | ); 101 | togglerElements.forEach((el) => (el.style.display = "")); 102 | if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); 103 | }, 104 | 105 | initOnKeyListeners: () => { 106 | // only install a listener if it is really needed 107 | if ( 108 | !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && 109 | !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS 110 | ) 111 | return; 112 | 113 | document.addEventListener("keydown", (event) => { 114 | // bail for input elements 115 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 116 | // bail with special keys 117 | if (event.altKey || event.ctrlKey || event.metaKey) return; 118 | 119 | if (!event.shiftKey) { 120 | switch (event.key) { 121 | case "ArrowLeft": 122 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 123 | 124 | const prevLink = document.querySelector('link[rel="prev"]'); 125 | if (prevLink && prevLink.href) { 126 | window.location.href = prevLink.href; 127 | event.preventDefault(); 128 | } 129 | break; 130 | case "ArrowRight": 131 | if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; 132 | 133 | const nextLink = document.querySelector('link[rel="next"]'); 134 | if (nextLink && nextLink.href) { 135 | window.location.href = nextLink.href; 136 | event.preventDefault(); 137 | } 138 | break; 139 | } 140 | } 141 | 142 | // some keyboard layouts may need Shift to get / 143 | switch (event.key) { 144 | case "/": 145 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; 146 | Documentation.focusSearchBar(); 147 | event.preventDefault(); 148 | } 149 | }); 150 | }, 151 | }; 152 | 153 | // quick alias for translations 154 | const _ = Documentation.gettext; 155 | 156 | _ready(Documentation.init); 157 | -------------------------------------------------------------------------------- /docs/_static/documentation_options.js: -------------------------------------------------------------------------------- 1 | var DOCUMENTATION_OPTIONS = { 2 | URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), 3 | VERSION: '1.4.9', 4 | LANGUAGE: 'en', 5 | COLLAPSE_INDEX: false, 6 | BUILDER: 'html', 7 | FILE_SUFFIX: '.html', 8 | LINK_SUFFIX: '.html', 9 | HAS_SOURCE: true, 10 | SOURCELINK_SUFFIX: '.txt', 11 | NAVIGATION_WITH_KEYS: false, 12 | SHOW_SEARCH_SUMMARY: true, 13 | ENABLE_SEARCH_SHORTCUTS: true, 14 | }; -------------------------------------------------------------------------------- /docs/_static/down-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/down-pressed.png -------------------------------------------------------------------------------- /docs/_static/down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/down.png -------------------------------------------------------------------------------- /docs/_static/epub.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: {{ theme_bodyfont }}; 18 | font-size: 100%; 19 | background-color: {{ theme_footerbgcolor }}; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: {{ theme_sidebarbgcolor }}; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: {{ theme_bgcolor }}; 40 | color: {{ theme_textcolor }}; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | {%- if theme_rightsidebar|tobool %} 45 | div.bodywrapper { 46 | margin: 0 230px 0 0; 47 | } 48 | {%- endif %} 49 | 50 | div.footer { 51 | color: {{ theme_footertextcolor }}; 52 | width: 100%; 53 | padding: 9px 0 9px 0; 54 | text-align: center; 55 | font-size: 75%; 56 | } 57 | 58 | div.footer a { 59 | color: {{ theme_footertextcolor }}; 60 | text-decoration: underline; 61 | } 62 | 63 | div.related { 64 | background-color: {{ theme_relbarbgcolor }}; 65 | line-height: 30px; 66 | color: {{ theme_relbartextcolor }}; 67 | } 68 | 69 | div.related a { 70 | color: {{ theme_relbarlinkcolor }}; 71 | } 72 | 73 | div.sphinxsidebar { 74 | {%- if theme_stickysidebar|tobool %} 75 | top: 30px; 76 | bottom: 0; 77 | margin: 0; 78 | position: fixed; 79 | overflow: auto; 80 | height: auto; 81 | {%- endif %} 82 | {%- if theme_rightsidebar|tobool %} 83 | float: right; 84 | {%- if theme_stickysidebar|tobool %} 85 | right: 0; 86 | {%- endif %} 87 | {%- endif %} 88 | } 89 | 90 | {%- if theme_stickysidebar|tobool %} 91 | /* this is nice, but it it leads to hidden headings when jumping 92 | to an anchor */ 93 | /* 94 | div.related { 95 | position: fixed; 96 | } 97 | 98 | div.documentwrapper { 99 | margin-top: 30px; 100 | } 101 | */ 102 | {%- endif %} 103 | 104 | div.sphinxsidebar h3 { 105 | font-family: {{ theme_headfont }}; 106 | color: {{ theme_sidebartextcolor }}; 107 | font-size: 1.4em; 108 | font-weight: normal; 109 | margin: 0; 110 | padding: 0; 111 | } 112 | 113 | div.sphinxsidebar h3 a { 114 | color: {{ theme_sidebartextcolor }}; 115 | } 116 | 117 | div.sphinxsidebar h4 { 118 | font-family: {{ theme_headfont }}; 119 | color: {{ theme_sidebartextcolor }}; 120 | font-size: 1.3em; 121 | font-weight: normal; 122 | margin: 5px 0 0 0; 123 | padding: 0; 124 | } 125 | 126 | div.sphinxsidebar p { 127 | color: {{ theme_sidebartextcolor }}; 128 | } 129 | 130 | div.sphinxsidebar p.topless { 131 | margin: 5px 10px 10px 10px; 132 | } 133 | 134 | div.sphinxsidebar ul { 135 | margin: 10px; 136 | padding: 0; 137 | color: {{ theme_sidebartextcolor }}; 138 | } 139 | 140 | div.sphinxsidebar a { 141 | color: {{ theme_sidebarlinkcolor }}; 142 | } 143 | 144 | div.sphinxsidebar input { 145 | border: 1px solid {{ theme_sidebarlinkcolor }}; 146 | font-family: sans-serif; 147 | font-size: 1em; 148 | } 149 | 150 | {% if theme_collapsiblesidebar|tobool %} 151 | /* for collapsible sidebar */ 152 | div#sidebarbutton { 153 | background-color: {{ theme_sidebarbtncolor }}; 154 | } 155 | {% endif %} 156 | 157 | /* -- hyperlink styles ------------------------------------------------------ */ 158 | 159 | a { 160 | color: {{ theme_linkcolor }}; 161 | text-decoration: none; 162 | } 163 | 164 | a:visited { 165 | color: {{ theme_visitedlinkcolor }}; 166 | text-decoration: none; 167 | } 168 | 169 | a:hover { 170 | text-decoration: underline; 171 | } 172 | 173 | {% if theme_externalrefs|tobool %} 174 | a.external { 175 | text-decoration: none; 176 | border-bottom: 1px dashed {{ theme_linkcolor }}; 177 | } 178 | 179 | a.external:hover { 180 | text-decoration: none; 181 | border-bottom: none; 182 | } 183 | 184 | a.external:visited { 185 | text-decoration: none; 186 | border-bottom: 1px dashed {{ theme_visitedlinkcolor }}; 187 | } 188 | {% endif %} 189 | 190 | /* -- body styles ----------------------------------------------------------- */ 191 | 192 | div.body h1, 193 | div.body h2, 194 | div.body h3, 195 | div.body h4, 196 | div.body h5, 197 | div.body h6 { 198 | font-family: {{ theme_headfont }}; 199 | background-color: {{ theme_headbgcolor }}; 200 | font-weight: normal; 201 | color: {{ theme_headtextcolor }}; 202 | border-bottom: 1px solid #ccc; 203 | margin: 20px -20px 10px -20px; 204 | padding: 3px 0 3px 10px; 205 | } 206 | 207 | div.body h1 { margin-top: 0; font-size: 200%; } 208 | div.body h2 { font-size: 160%; } 209 | div.body h3 { font-size: 140%; } 210 | div.body h4 { font-size: 120%; } 211 | div.body h5 { font-size: 110%; } 212 | div.body h6 { font-size: 100%; } 213 | 214 | a.headerlink { 215 | color: {{ theme_headlinkcolor }}; 216 | font-size: 0.8em; 217 | padding: 0 4px 0 4px; 218 | text-decoration: none; 219 | } 220 | 221 | a.headerlink:hover { 222 | background-color: {{ theme_headlinkcolor }}; 223 | color: white; 224 | } 225 | 226 | div.body p, div.body dd, div.body li { 227 | text-align: justify; 228 | line-height: 130%; 229 | } 230 | 231 | div.admonition p.admonition-title + p { 232 | display: inline; 233 | } 234 | 235 | div.admonition p { 236 | margin-bottom: 5px; 237 | } 238 | 239 | div.admonition pre { 240 | margin-bottom: 5px; 241 | } 242 | 243 | div.admonition ul, div.admonition ol { 244 | margin-bottom: 5px; 245 | } 246 | 247 | div.note { 248 | background-color: #eee; 249 | border: 1px solid #ccc; 250 | } 251 | 252 | div.seealso { 253 | background-color: #ffc; 254 | border: 1px solid #ff6; 255 | } 256 | 257 | div.topic { 258 | background-color: #eee; 259 | } 260 | 261 | div.warning { 262 | background-color: #ffe4e4; 263 | border: 1px solid #f66; 264 | } 265 | 266 | p.admonition-title { 267 | display: inline; 268 | } 269 | 270 | p.admonition-title:after { 271 | content: ":"; 272 | } 273 | 274 | pre { 275 | padding: 5px; 276 | background-color: {{ theme_codebgcolor }}; 277 | color: {{ theme_codetextcolor }}; 278 | line-height: 120%; 279 | border: 1px solid #ac9; 280 | border-left: none; 281 | border-right: none; 282 | } 283 | 284 | tt { 285 | background-color: #ecf0f3; 286 | padding: 0 1px 0 1px; 287 | font-size: 0.95em; 288 | } 289 | 290 | th { 291 | background-color: #ede; 292 | } 293 | 294 | .warning tt { 295 | background: #efc2c2; 296 | } 297 | 298 | .note tt { 299 | background: #d6d6d6; 300 | } 301 | 302 | .viewcode-back { 303 | font-family: {{ theme_bodyfont }}; 304 | } 305 | 306 | div.viewcode-block:target { 307 | background-color: #f4debf; 308 | border-top: 1px solid #ac9; 309 | border-bottom: 1px solid #ac9; 310 | } 311 | -------------------------------------------------------------------------------- /docs/_static/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/file.png -------------------------------------------------------------------------------- /docs/_static/footerbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/footerbg.png -------------------------------------------------------------------------------- /docs/_static/headerbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/headerbg.png -------------------------------------------------------------------------------- /docs/_static/ie6.css: -------------------------------------------------------------------------------- 1 | * html img, 2 | * html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none", 3 | this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')", 4 | this.src = "_static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''), 5 | this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')", 6 | this.runtimeStyle.backgroundImage = "none")),this.pngSet=true) 7 | );} 8 | -------------------------------------------------------------------------------- /docs/_static/language_data.js: -------------------------------------------------------------------------------- 1 | /* 2 | * language_data.js 3 | * ~~~~~~~~~~~~~~~~ 4 | * 5 | * This script contains the language-specific data used by searchtools.js, 6 | * namely the list of stopwords, stemmer, scorer and splitter. 7 | * 8 | * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. 9 | * :license: BSD, see LICENSE for details. 10 | * 11 | */ 12 | 13 | var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; 14 | 15 | 16 | /* Non-minified version is copied as a separate JS file, is available */ 17 | 18 | /** 19 | * Porter Stemmer 20 | */ 21 | var Stemmer = function() { 22 | 23 | var step2list = { 24 | ational: 'ate', 25 | tional: 'tion', 26 | enci: 'ence', 27 | anci: 'ance', 28 | izer: 'ize', 29 | bli: 'ble', 30 | alli: 'al', 31 | entli: 'ent', 32 | eli: 'e', 33 | ousli: 'ous', 34 | ization: 'ize', 35 | ation: 'ate', 36 | ator: 'ate', 37 | alism: 'al', 38 | iveness: 'ive', 39 | fulness: 'ful', 40 | ousness: 'ous', 41 | aliti: 'al', 42 | iviti: 'ive', 43 | biliti: 'ble', 44 | logi: 'log' 45 | }; 46 | 47 | var step3list = { 48 | icate: 'ic', 49 | ative: '', 50 | alize: 'al', 51 | iciti: 'ic', 52 | ical: 'ic', 53 | ful: '', 54 | ness: '' 55 | }; 56 | 57 | var c = "[^aeiou]"; // consonant 58 | var v = "[aeiouy]"; // vowel 59 | var C = c + "[^aeiouy]*"; // consonant sequence 60 | var V = v + "[aeiou]*"; // vowel sequence 61 | 62 | var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 63 | var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 64 | var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 65 | var s_v = "^(" + C + ")?" + v; // vowel in stem 66 | 67 | this.stemWord = function (w) { 68 | var stem; 69 | var suffix; 70 | var firstch; 71 | var origword = w; 72 | 73 | if (w.length < 3) 74 | return w; 75 | 76 | var re; 77 | var re2; 78 | var re3; 79 | var re4; 80 | 81 | firstch = w.substr(0,1); 82 | if (firstch == "y") 83 | w = firstch.toUpperCase() + w.substr(1); 84 | 85 | // Step 1a 86 | re = /^(.+?)(ss|i)es$/; 87 | re2 = /^(.+?)([^s])s$/; 88 | 89 | if (re.test(w)) 90 | w = w.replace(re,"$1$2"); 91 | else if (re2.test(w)) 92 | w = w.replace(re2,"$1$2"); 93 | 94 | // Step 1b 95 | re = /^(.+?)eed$/; 96 | re2 = /^(.+?)(ed|ing)$/; 97 | if (re.test(w)) { 98 | var fp = re.exec(w); 99 | re = new RegExp(mgr0); 100 | if (re.test(fp[1])) { 101 | re = /.$/; 102 | w = w.replace(re,""); 103 | } 104 | } 105 | else if (re2.test(w)) { 106 | var fp = re2.exec(w); 107 | stem = fp[1]; 108 | re2 = new RegExp(s_v); 109 | if (re2.test(stem)) { 110 | w = stem; 111 | re2 = /(at|bl|iz)$/; 112 | re3 = new RegExp("([^aeiouylsz])\\1$"); 113 | re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 114 | if (re2.test(w)) 115 | w = w + "e"; 116 | else if (re3.test(w)) { 117 | re = /.$/; 118 | w = w.replace(re,""); 119 | } 120 | else if (re4.test(w)) 121 | w = w + "e"; 122 | } 123 | } 124 | 125 | // Step 1c 126 | re = /^(.+?)y$/; 127 | if (re.test(w)) { 128 | var fp = re.exec(w); 129 | stem = fp[1]; 130 | re = new RegExp(s_v); 131 | if (re.test(stem)) 132 | w = stem + "i"; 133 | } 134 | 135 | // Step 2 136 | re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; 137 | if (re.test(w)) { 138 | var fp = re.exec(w); 139 | stem = fp[1]; 140 | suffix = fp[2]; 141 | re = new RegExp(mgr0); 142 | if (re.test(stem)) 143 | w = stem + step2list[suffix]; 144 | } 145 | 146 | // Step 3 147 | re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; 148 | if (re.test(w)) { 149 | var fp = re.exec(w); 150 | stem = fp[1]; 151 | suffix = fp[2]; 152 | re = new RegExp(mgr0); 153 | if (re.test(stem)) 154 | w = stem + step3list[suffix]; 155 | } 156 | 157 | // Step 4 158 | re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; 159 | re2 = /^(.+?)(s|t)(ion)$/; 160 | if (re.test(w)) { 161 | var fp = re.exec(w); 162 | stem = fp[1]; 163 | re = new RegExp(mgr1); 164 | if (re.test(stem)) 165 | w = stem; 166 | } 167 | else if (re2.test(w)) { 168 | var fp = re2.exec(w); 169 | stem = fp[1] + fp[2]; 170 | re2 = new RegExp(mgr1); 171 | if (re2.test(stem)) 172 | w = stem; 173 | } 174 | 175 | // Step 5 176 | re = /^(.+?)e$/; 177 | if (re.test(w)) { 178 | var fp = re.exec(w); 179 | stem = fp[1]; 180 | re = new RegExp(mgr1); 181 | re2 = new RegExp(meq1); 182 | re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); 183 | if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) 184 | w = stem; 185 | } 186 | re = /ll$/; 187 | re2 = new RegExp(mgr1); 188 | if (re.test(w) && re2.test(w)) { 189 | re = /.$/; 190 | w = w.replace(re,""); 191 | } 192 | 193 | // and turn initial Y back to y 194 | if (firstch == "y") 195 | w = firstch.toLowerCase() + w.substr(1); 196 | return w; 197 | } 198 | } 199 | 200 | -------------------------------------------------------------------------------- /docs/_static/middlebg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/middlebg.png -------------------------------------------------------------------------------- /docs/_static/minus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/minus.png -------------------------------------------------------------------------------- /docs/_static/plus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/plus.png -------------------------------------------------------------------------------- /docs/_static/pygments.css: -------------------------------------------------------------------------------- 1 | pre { line-height: 125%; } 2 | td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } 3 | span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } 4 | td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } 5 | span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } 6 | .highlight .hll { background-color: #ffffcc } 7 | .highlight { background: #eeffcc; } 8 | .highlight .c { color: #408090; font-style: italic } /* Comment */ 9 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 10 | .highlight .k { color: #007020; font-weight: bold } /* Keyword */ 11 | .highlight .o { color: #666666 } /* Operator */ 12 | .highlight .ch { color: #408090; font-style: italic } /* Comment.Hashbang */ 13 | .highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */ 14 | .highlight .cp { color: #007020 } /* Comment.Preproc */ 15 | .highlight .cpf { color: #408090; font-style: italic } /* Comment.PreprocFile */ 16 | .highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */ 17 | .highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */ 18 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 19 | .highlight .ge { font-style: italic } /* Generic.Emph */ 20 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 21 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 22 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 23 | .highlight .go { color: #333333 } /* Generic.Output */ 24 | .highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */ 25 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 26 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 27 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 28 | .highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */ 29 | .highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */ 30 | .highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */ 31 | .highlight .kp { color: #007020 } /* Keyword.Pseudo */ 32 | .highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */ 33 | .highlight .kt { color: #902000 } /* Keyword.Type */ 34 | .highlight .m { color: #208050 } /* Literal.Number */ 35 | .highlight .s { color: #4070a0 } /* Literal.String */ 36 | .highlight .na { color: #4070a0 } /* Name.Attribute */ 37 | .highlight .nb { color: #007020 } /* Name.Builtin */ 38 | .highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */ 39 | .highlight .no { color: #60add5 } /* Name.Constant */ 40 | .highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */ 41 | .highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */ 42 | .highlight .ne { color: #007020 } /* Name.Exception */ 43 | .highlight .nf { color: #06287e } /* Name.Function */ 44 | .highlight .nl { color: #002070; font-weight: bold } /* Name.Label */ 45 | .highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */ 46 | .highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */ 47 | .highlight .nv { color: #bb60d5 } /* Name.Variable */ 48 | .highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */ 49 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 50 | .highlight .mb { color: #208050 } /* Literal.Number.Bin */ 51 | .highlight .mf { color: #208050 } /* Literal.Number.Float */ 52 | .highlight .mh { color: #208050 } /* Literal.Number.Hex */ 53 | .highlight .mi { color: #208050 } /* Literal.Number.Integer */ 54 | .highlight .mo { color: #208050 } /* Literal.Number.Oct */ 55 | .highlight .sa { color: #4070a0 } /* Literal.String.Affix */ 56 | .highlight .sb { color: #4070a0 } /* Literal.String.Backtick */ 57 | .highlight .sc { color: #4070a0 } /* Literal.String.Char */ 58 | .highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */ 59 | .highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */ 60 | .highlight .s2 { color: #4070a0 } /* Literal.String.Double */ 61 | .highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */ 62 | .highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */ 63 | .highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */ 64 | .highlight .sx { color: #c65d09 } /* Literal.String.Other */ 65 | .highlight .sr { color: #235388 } /* Literal.String.Regex */ 66 | .highlight .s1 { color: #4070a0 } /* Literal.String.Single */ 67 | .highlight .ss { color: #517918 } /* Literal.String.Symbol */ 68 | .highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */ 69 | .highlight .fm { color: #06287e } /* Name.Function.Magic */ 70 | .highlight .vc { color: #bb60d5 } /* Name.Variable.Class */ 71 | .highlight .vg { color: #bb60d5 } /* Name.Variable.Global */ 72 | .highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */ 73 | .highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */ 74 | .highlight .il { color: #208050 } /* Literal.Number.Integer.Long */ -------------------------------------------------------------------------------- /docs/_static/sphinx_highlight.js: -------------------------------------------------------------------------------- 1 | /* Highlighting utilities for Sphinx HTML documentation. */ 2 | "use strict"; 3 | 4 | const SPHINX_HIGHLIGHT_ENABLED = true 5 | 6 | /** 7 | * highlight a given string on a node by wrapping it in 8 | * span elements with the given class name. 9 | */ 10 | const _highlight = (node, addItems, text, className) => { 11 | if (node.nodeType === Node.TEXT_NODE) { 12 | const val = node.nodeValue; 13 | const parent = node.parentNode; 14 | const pos = val.toLowerCase().indexOf(text); 15 | if ( 16 | pos >= 0 && 17 | !parent.classList.contains(className) && 18 | !parent.classList.contains("nohighlight") 19 | ) { 20 | let span; 21 | 22 | const closestNode = parent.closest("body, svg, foreignObject"); 23 | const isInSVG = closestNode && closestNode.matches("svg"); 24 | if (isInSVG) { 25 | span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); 26 | } else { 27 | span = document.createElement("span"); 28 | span.classList.add(className); 29 | } 30 | 31 | span.appendChild(document.createTextNode(val.substr(pos, text.length))); 32 | parent.insertBefore( 33 | span, 34 | parent.insertBefore( 35 | document.createTextNode(val.substr(pos + text.length)), 36 | node.nextSibling 37 | ) 38 | ); 39 | node.nodeValue = val.substr(0, pos); 40 | 41 | if (isInSVG) { 42 | const rect = document.createElementNS( 43 | "http://www.w3.org/2000/svg", 44 | "rect" 45 | ); 46 | const bbox = parent.getBBox(); 47 | rect.x.baseVal.value = bbox.x; 48 | rect.y.baseVal.value = bbox.y; 49 | rect.width.baseVal.value = bbox.width; 50 | rect.height.baseVal.value = bbox.height; 51 | rect.setAttribute("class", className); 52 | addItems.push({ parent: parent, target: rect }); 53 | } 54 | } 55 | } else if (node.matches && !node.matches("button, select, textarea")) { 56 | node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); 57 | } 58 | }; 59 | const _highlightText = (thisNode, text, className) => { 60 | let addItems = []; 61 | _highlight(thisNode, addItems, text, className); 62 | addItems.forEach((obj) => 63 | obj.parent.insertAdjacentElement("beforebegin", obj.target) 64 | ); 65 | }; 66 | 67 | /** 68 | * Small JavaScript module for the documentation. 69 | */ 70 | const SphinxHighlight = { 71 | 72 | /** 73 | * highlight the search words provided in localstorage in the text 74 | */ 75 | highlightSearchWords: () => { 76 | if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight 77 | 78 | // get and clear terms from localstorage 79 | const url = new URL(window.location); 80 | const highlight = 81 | localStorage.getItem("sphinx_highlight_terms") 82 | || url.searchParams.get("highlight") 83 | || ""; 84 | localStorage.removeItem("sphinx_highlight_terms") 85 | url.searchParams.delete("highlight"); 86 | window.history.replaceState({}, "", url); 87 | 88 | // get individual terms from highlight string 89 | const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); 90 | if (terms.length === 0) return; // nothing to do 91 | 92 | // There should never be more than one element matching "div.body" 93 | const divBody = document.querySelectorAll("div.body"); 94 | const body = divBody.length ? divBody[0] : document.querySelector("body"); 95 | window.setTimeout(() => { 96 | terms.forEach((term) => _highlightText(body, term, "highlighted")); 97 | }, 10); 98 | 99 | const searchBox = document.getElementById("searchbox"); 100 | if (searchBox === null) return; 101 | searchBox.appendChild( 102 | document 103 | .createRange() 104 | .createContextualFragment( 105 | '" 109 | ) 110 | ); 111 | }, 112 | 113 | /** 114 | * helper function to hide the search marks again 115 | */ 116 | hideSearchWords: () => { 117 | document 118 | .querySelectorAll("#searchbox .highlight-link") 119 | .forEach((el) => el.remove()); 120 | document 121 | .querySelectorAll("span.highlighted") 122 | .forEach((el) => el.classList.remove("highlighted")); 123 | localStorage.removeItem("sphinx_highlight_terms") 124 | }, 125 | 126 | initEscapeListener: () => { 127 | // only install a listener if it is really needed 128 | if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; 129 | 130 | document.addEventListener("keydown", (event) => { 131 | // bail for input elements 132 | if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; 133 | // bail with special keys 134 | if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; 135 | if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { 136 | SphinxHighlight.hideSearchWords(); 137 | event.preventDefault(); 138 | } 139 | }); 140 | }, 141 | }; 142 | 143 | _ready(SphinxHighlight.highlightSearchWords); 144 | _ready(SphinxHighlight.initEscapeListener); 145 | -------------------------------------------------------------------------------- /docs/_static/transparent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/transparent.gif -------------------------------------------------------------------------------- /docs/_static/up-pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/up-pressed.png -------------------------------------------------------------------------------- /docs/_static/up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/_static/up.png -------------------------------------------------------------------------------- /docs/changelog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Changelog — Interbase 1.4.9 documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 45 | 46 |
47 |
48 |
49 |
50 | 51 |
52 |

Changelog

53 | 56 |
57 |

Version 1.5.0

58 |
59 |
60 | 61 | 62 |
63 |
64 |
65 |
66 | 107 |
108 |
109 | 128 | 132 | 133 | -------------------------------------------------------------------------------- /docs/license.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | LICENSE — Interbase 1.4.9 documentation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 41 | 42 |
43 |
44 |
45 |
46 | 47 |
48 |

LICENSE

49 |

The following contributors hold Copyright (c) over their respective portions 50 | of code and documentation:

51 |

Contributors:

52 |
53 |
[The main portion of initial code (~95%)]

Pavel Cisar <pcisar@ibphoenix.cz>

54 |
55 |
[Author of blog post with instructions for converting driver to work with InterBase ]

Gabe Goldfield <https://community.embarcadero.com/view-profile/6168-gabriel>

56 |
57 |
[Initial trace API & nbackup support; Python 3 support]

Philippe Makowski <pmakowski@espelida.com>

58 |
59 |
60 |

Some code in inital version is Python code from KInterbasDB 3.3.0. 61 | As it’s very hard to find out who exactly was the original author of used code, 62 | here is the full list of KInterbasDB contributors:

63 |

[Author of original version; maintained through version 2.0:]

64 |
65 |

1998-2001 [alex] Alexander Kuznetsov <alexan@users.sourceforge.net>

66 |
67 |

[Author of ~90% of current code, most of current documentation; maintained through version 3.3:]

68 |
69 |

2002-2007 [dsr] David S. Rushby <woodsplitter@rocketmail.com>

70 |
71 |

[Finishing touch to v3.3; New Documentation; Current maintainer:]

72 |
73 |

2008-2011 [paci] Pavel Cisar <pcisar@ibphoenix.cz>

74 |
75 |

[Significant Contributors:]

76 |
77 |

2001-2002 [maz] Marek Isalski <kinterbasdb@maz.nu>

78 |
79 |

Marek made important first steps in removing the limitations of version 2.0 80 | in preparation for version 3.0.

81 |
82 |

2001 [eac] Evgeny A. Cherkashin <eugeneai@icc.ru>

83 |
84 |

Evgeny wrote the first version of the distutils build script, 85 | which was included in a 2.x point release.

86 |
87 |

2001-2002 [janez] Janez Jere <janez.jere@void.si>

88 |
89 |

Janez contributed several bugfixes, including fixes for the date and time 90 | parameter conversion code in preparation for version 3.0.

91 |
92 |
93 |

Permission to use, copy, modify, and distribute this software and its documentation 94 | for any purpose and without fee or royalty is hereby granted, provided that the above 95 | copyright notice appears in all copies and that both the copyright notice and 96 | this permission notice appear in supporting documentation or portions thereof, 97 | including modifications, that you make.

98 |

The authors disclaim all warranties with regard to this software, including all 99 | implied warranties of merchantability and fitness. In no event shall any author 100 | be liable for any special, indirect or consequential damages or any damages whatsoever 101 | resulting from loss of use, data or profits, whether in an action of contract, 102 | negligence or other tortious action, arising out of or in connection with the use 103 | or performance of this software.

104 |
105 | 106 | 107 |
108 |
109 |
110 |
111 | 137 |
138 |
139 | 155 | 159 | 160 | -------------------------------------------------------------------------------- /docs/listinv.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from sphinx.ext import intersphinx 3 | 4 | class DummyApp(object): 5 | srcdir = "." 6 | 7 | def warn(self, msg): 8 | sys.stderr.write("%s\n" % msg) 9 | 10 | def main(): 11 | app = DummyApp() 12 | # baseurl to use 13 | uri = "" 14 | inv = sys.argv[1] 15 | inventory = intersphinx.fetch_inventory(app, uri, inv) 16 | for k in inventory.keys(): 17 | print "Type: %s" % k 18 | for name, value in inventory[k].items(): 19 | print " %s -> '%s'" % (name, value[2]) 20 | 21 | return 0 22 | 23 | if __name__ == "__main__": 24 | sys.exit(main()) 25 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /docs/objects.inv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/docs/objects.inv -------------------------------------------------------------------------------- /docs/py-modindex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Python Module Index — Interbase 1.4.9 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 21 | 22 | 23 | 24 | 25 | 26 | 39 | 40 |
41 |
42 |
43 |
44 | 45 | 46 |

Python Module Index

47 | 48 |
49 | i 50 |
51 | 52 | 53 | 54 | 56 | 57 | 59 | 62 | 63 | 64 | 67 | 68 | 69 | 72 | 73 | 74 | 77 | 78 | 79 | 82 | 83 | 84 | 87 | 88 | 89 | 92 |
 
55 | i
60 | interbase 61 | Python Database API 2.0 Compliant driver for InterBase
    65 | interbase.blr 66 | Python ctypes interface to InterBase client library (BLR)
    70 | interbase.ibase 71 | Python ctypes interface to InterBase client library
    75 | interbase.ibcore 76 | Implementation of InterBase driver
    80 | interbase.schema 81 | Submodule for work with database metadata (schema)
    85 | interbase.services 86 | Submodule for work with InterBase Services
    90 | interbase.utils 91 | Submodule with various classes and functions
93 | 94 | 95 |
96 |
97 |
98 |
99 | 113 |
114 |
115 | 128 | 132 | 133 | -------------------------------------------------------------------------------- /docs/requirements.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <no title> — IDB 1.4.9 documentation 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 38 | 39 |
40 |
41 |
42 |
43 | 44 |

idb

45 | 46 | 47 |
48 |
49 |
50 |
51 | 72 |
73 |
74 | 87 | 91 | 92 | -------------------------------------------------------------------------------- /docs/search.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Search — Interbase 1.4.9 documentation 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 29 | 42 | 43 |
44 |
45 |
46 |
47 | 48 |

Search

49 | 50 | 58 | 59 | 60 |

61 | Searching for multiple words only shows matches that contain 62 | all words. 63 |

64 | 65 | 66 |
67 | 68 | 69 | 70 |
71 | 72 | 73 | 74 |
75 | 76 |
77 | 78 | 79 |
80 |
81 |
82 |
83 | 87 |
88 |
89 | 102 | 106 | 107 | -------------------------------------------------------------------------------- /docs/source/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # For the full list of built-in configuration values, see the documentation: 4 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 5 | 6 | # -- Project information ----------------------------------------------------- 7 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information 8 | 9 | project = 'idb' 10 | copyright = '2023, me' 11 | author = 'me' 12 | 13 | # -- General configuration --------------------------------------------------- 14 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration 15 | 16 | extensions = [] 17 | 18 | templates_path = ['_templates'] 19 | exclude_patterns = [] 20 | 21 | 22 | 23 | # -- Options for HTML output ------------------------------------------------- 24 | # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output 25 | 26 | html_theme = 'alabaster' 27 | html_static_path = ['_static'] 28 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | .. idb documentation master file, created by 2 | sphinx-quickstart on Mon Mar 13 13:14:57 2023. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to idb's documentation! 7 | =============================== 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | :caption: Contents: 12 | 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /interbase/__init__.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: __init__.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 8.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | from interbase.ibcore import * 28 | from interbase.ibcore import __version__ 29 | from interbase import services 30 | 31 | __all__ = ( 32 | 'BINARY', 'Binary', 'BlobReader', 'Connection', 'ConnectionGroup', 33 | 'Cursor', 'DATETIME', 'DBAPITypeObject', 'DESCRIPTION_DISPLAY_SIZE', 34 | 'DESCRIPTION_INTERNAL_SIZE', 'DESCRIPTION_NAME', 'DESCRIPTION_NULL_OK', 35 | 'DESCRIPTION_PRECISION', 'DESCRIPTION_SCALE', 'DESCRIPTION_TYPE_CODE', 36 | 'DIST_TRANS_MAX_DATABASES', 'DataError', 'DatabaseError', 'Date', 37 | 'DateFromTicks', 'Error', 'EventConduit', 'IntegrityError', 38 | 'InterfaceError', 'InternalError', 'NUMBER', 'NotSupportedError', 39 | 'OperationalError', 'PreparedStatement', 'ProgrammingError', 'ROWID', 40 | 'STRING', 'TPB', 'TableReservation', 'Time', 'TimeFromTicks', 41 | 'TimestampFromTicks', 'Transaction', 'TransactionConflict', 'Warning', 42 | '__version__', 'apilevel', 'connect', 'create_database', 43 | 'isc_dpb_activate_shadow', 'isc_dpb_address_path', 44 | 'isc_dpb_allocation', 'isc_dpb_begin_log', 'isc_dpb_buffer_length', 45 | 'isc_dpb_cache_manager', 'isc_dpb_cdd_pathname', 'isc_dpb_connect_timeout', 46 | 'isc_dpb_damaged', 'isc_dpb_dbkey_scope', 'isc_dpb_debug', 47 | 'isc_dpb_delete_shadow', 'isc_dpb_disable_journal', 'isc_dpb_disable_wal', 48 | 'isc_dpb_drop_walfile', 'isc_dpb_dummy_packet_interval', 49 | 'isc_dpb_enable_journal', 'isc_dpb_encrypt_key', 'isc_dpb_force_write', 50 | 'isc_dpb_garbage_collect', 'isc_dpb_gbak_attach', 'isc_dpb_gfix_attach', 51 | 'isc_dpb_gsec_attach', 'isc_dpb_gstat_attach', 'isc_dpb_interp', 52 | 'isc_dpb_journal', 'isc_dpb_lc_ctype', 'isc_dpb_lc_messages', 53 | 'isc_dpb_license', 'isc_dpb_no_garbage_collect', 'isc_dpb_no_reserve', 54 | 'isc_dpb_num_buffers', 'isc_dpb_number_of_users', 'isc_dpb_old_dump_id', 55 | 'isc_dpb_old_file', 'isc_dpb_old_file_size', 'isc_dpb_old_num_files', 56 | 'isc_dpb_old_start_file', 'isc_dpb_old_start_page', 'isc_dpb_old_start_seqno', 57 | 'isc_dpb_online', 'isc_dpb_online_dump', 'isc_dpb_overwrite', 58 | 'isc_dpb_page_size', 'isc_dpb_password', 'isc_dpb_password_enc', 59 | 'isc_dpb_quit_log', 'isc_dpb_reserved', 'isc_dpb_sec_attach', 60 | 'isc_dpb_set_db_charset', 'isc_dpb_set_db_readonly', 61 | 'isc_dpb_set_db_sql_dialect', 'isc_dpb_set_page_buffers', 62 | 'isc_dpb_shutdown', 'isc_dpb_shutdown_delay', 'isc_dpb_sql_dialect', 63 | 'isc_dpb_sql_role_name', 'isc_dpb_sweep', 'isc_dpb_sweep_interval', 64 | 'isc_dpb_sys_user_name', 'isc_dpb_sys_user_name_enc', 'isc_dpb_trace', 65 | 'isc_dpb_user_name', 'isc_dpb_verify', 'isc_dpb_version1', 66 | 'isc_dpb_wal_backup_dir', 'isc_dpb_wal_bufsize', 'isc_dpb_wal_chkptlen', 67 | 'isc_dpb_wal_grp_cmt_wait', 'isc_dpb_wal_numbufs', 'isc_dpb_working_directory', 68 | 'isc_info_allocation', 'isc_info_attachment_id', 'isc_info_backout_count', 69 | 'isc_info_base_level', 'isc_info_bpage_errors', 70 | 'isc_info_cur_log_part_offset', 'isc_info_cur_logfile_name', 71 | 'isc_info_current_memory', 72 | 'isc_info_db_id', 'isc_info_db_read_only', 73 | 'isc_info_db_size_in_pages', 'isc_info_db_sql_dialect', 74 | 'isc_info_delete_count', 'isc_info_dpage_errors', 'isc_info_expunge_count', 75 | 'isc_info_fetches', 'isc_info_forced_writes', 76 | 'isc_info_implementation', 'isc_info_insert_count', 'isc_info_ipage_errors', 77 | 'isc_info_isc_version', 'isc_info_license', 'isc_info_limbo', 78 | 'isc_info_logfile', 'isc_info_marks', 'isc_info_max_memory', 79 | 'isc_info_no_reserve', 'isc_info_num_buffers', 80 | 'isc_info_num_wal_buffers', 'isc_info_ods_minor_version', 81 | 'isc_info_ods_version', 82 | 'isc_info_page_errors', 'isc_info_page_size', 83 | 'isc_info_ppage_errors', 'isc_info_purge_count', 'isc_info_read_idx_count', 84 | 'isc_info_read_seq_count', 'isc_info_reads', 'isc_info_record_errors', 85 | 'isc_info_set_page_buffers', 'isc_info_sql_stmt_commit', 86 | 'isc_info_sql_stmt_ddl', 'isc_info_sql_stmt_delete', 87 | 'isc_info_sql_stmt_exec_procedure', 'isc_info_sql_stmt_get_segment', 88 | 'isc_info_sql_stmt_insert', 'isc_info_sql_stmt_put_segment', 89 | 'isc_info_sql_stmt_rollback', 'isc_info_sql_stmt_savepoint', 90 | 'isc_info_sql_stmt_select', 'isc_info_sql_stmt_select_for_upd', 91 | 'isc_info_sql_stmt_set_generator', 'isc_info_sql_stmt_start_trans', 92 | 'isc_info_sql_stmt_update', 'isc_info_sweep_interval', 'isc_info_tpage_errors', 93 | 'isc_info_tra_access', 'isc_info_tra_concurrency', 'isc_info_tra_consistency', 94 | 'isc_info_tra_id', 'isc_info_tra_isolation', 'isc_info_tra_lock_timeout', 95 | 'isc_info_tra_no_rec_version', 'isc_info_tra_oldest_active', 96 | 'isc_info_tra_oldest_interesting', 'isc_info_tra_oldest_snapshot', 97 | 'isc_info_tra_read_committed', 'isc_info_tra_readonly', 98 | 'isc_info_tra_readwrite', 'isc_info_tra_rec_version', 'isc_info_update_count', 99 | 'isc_info_user_names', 'isc_info_version', 'isc_info_wal_avg_grpc_size', 100 | 'isc_info_wal_avg_io_size', 'isc_info_wal_buffer_size', 101 | 'isc_info_wal_ckpt_length', 'isc_info_wal_cur_ckpt_interval', 102 | 'isc_info_wal_grpc_wait_usecs', 'isc_info_wal_num_commits', 103 | 'isc_info_wal_num_io', 'isc_info_wal_prv_ckpt_fname', 104 | 'isc_info_wal_prv_ckpt_poffset', 'isc_info_wal_recv_ckpt_fname', 105 | 'isc_info_wal_recv_ckpt_poffset', 'isc_info_window_turns', 106 | 'isc_info_writes', 'isc_tpb_autocommit', 'isc_tpb_commit_time', 107 | 'isc_tpb_concurrency', 'isc_tpb_consistency', 'isc_tpb_exclusive', 108 | 'isc_tpb_ignore_limbo', 'isc_tpb_lock_read', 'isc_tpb_lock_timeout', 109 | 'isc_tpb_lock_write', 'isc_tpb_no_auto_undo', 'isc_tpb_no_rec_version', 110 | 'isc_tpb_nowait', 'isc_tpb_protected', 'isc_tpb_read', 111 | 'isc_tpb_read_committed', 'isc_tpb_rec_version', 'isc_tpb_restart_requests', 112 | 'isc_tpb_shared', 'isc_tpb_verb_time', 'isc_tpb_version3', 'isc_tpb_wait', 113 | 'isc_tpb_write', 'paramstyle', 'threadsafety', 114 | # New in Interbase 115 | 'ISOLATION_LEVEL_READ_COMMITED', 'ISOLATION_LEVEL_READ_COMMITED_LEGACY', 116 | 'ISOLATION_LEVEL_REPEATABLE_READ', 'ISOLATION_LEVEL_SERIALIZABLE', 117 | 'ISOLATION_LEVEL_SNAPSHOT', 'ISOLATION_LEVEL_SNAPSHOT_TABLE_STABILITY', 118 | 'ISOLATION_LEVEL_READ_COMMITED_RO', 119 | 'MAX_BLOB_SEGMENT_SIZE', 120 | 'SQL_ARRAY', 'SQL_BLOB', 'SQL_DOUBLE', 'SQL_D_FLOAT', 'SQL_FLOAT', 121 | 'SQL_INT64', 'SQL_LONG', 'SQL_QUAD', 'SQL_SHORT', 'SQL_TEXT', 122 | 'SQL_TIMESTAMP', 'SQL_TYPE_DATE', 'SQL_TYPE_TIME', 'SQL_VARYING', 123 | 'SQL_BOOLEAN', 'SUBTYPE_DECIMAL', 'SUBTYPE_NUMERIC', 'build_dpb', 124 | 'charset_map', 125 | 'isc_info_end', 'isc_sqlcode', 'bs', 126 | ) 127 | -------------------------------------------------------------------------------- /interbase/blr.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: blr.py 5 | # DESCRIPTION: BLR-related definitions 6 | # CREATED: 12.6.2013 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | 28 | blr_inner = 0 29 | blr_left = 1 30 | blr_right = 2 31 | blr_full = 3 32 | 33 | blr_gds_code = 0 34 | blr_sql_code = 1 35 | blr_exception = 2 36 | blr_trigger_code = 3 37 | blr_default_code = 4 38 | blr_raise = 5 39 | blr_exception_msg = 6 40 | 41 | blr_version4 = 4 42 | blr_version5 = 5 43 | blr_eoc = 76 44 | blr_end = 255 45 | 46 | blr_assignment = 1 47 | blr_begin = 2 48 | blr_dcl_variable = 3 49 | blr_message = 4 50 | blr_erase = 5 51 | blr_fetch = 6 52 | blr_for = 7 53 | blr_if = 8 54 | blr_loop = 9 55 | blr_modify = 10 56 | blr_handler = 11 57 | blr_receive = 12 58 | blr_select = 13 59 | blr_send = 14 60 | blr_store = 15 61 | blr_label = 17 62 | blr_leave = 18 63 | blr_store2 = 19 64 | blr_post = 20 65 | blr_literal = 21 66 | blr_dbkey = 22 67 | blr_field = 23 68 | blr_fid = 24 69 | blr_parameter = 25 70 | blr_variable = 26 71 | blr_average = 27 72 | blr_count = 28 73 | blr_maximum = 29 74 | blr_minimum = 30 75 | blr_total = 31 76 | blr_add = 34 77 | blr_subtract = 35 78 | blr_multiply = 36 79 | blr_divide = 37 80 | blr_negate = 38 81 | blr_concatenate = 39 82 | blr_substring = 40 83 | blr_parameter2 = 41 84 | blr_from = 42 85 | blr_via = 43 86 | blr_parameter2_old = 44 87 | blr_user_name = 44 88 | blr_null = 45 89 | blr_equiv = 46 90 | blr_eql = 47 91 | blr_neq = 48 92 | blr_gtr = 49 93 | blr_geq = 50 94 | blr_lss = 51 95 | blr_leq = 52 96 | blr_containing = 53 97 | blr_matching = 54 98 | blr_starting = 55 99 | blr_between = 56 100 | blr_or = 57 101 | blr_and = 58 102 | blr_not = 59 103 | blr_any = 60 104 | blr_missing = 61 105 | blr_unique = 62 106 | blr_like = 63 107 | blr_rse = 67 108 | blr_first = 68 109 | blr_project = 69 110 | blr_sort = 70 111 | blr_boolean = 71 112 | blr_ascending = 72 113 | blr_descending = 73 114 | blr_relation = 74 115 | blr_rid = 75 116 | blr_union = 76 117 | blr_map = 77 118 | blr_group_by = 78 119 | blr_aggregate = 79 120 | blr_join_type = 80 121 | blr_agg_count = 83 122 | blr_agg_max = 84 123 | blr_agg_min = 85 124 | blr_agg_total = 86 125 | blr_agg_average = 87 126 | blr_parameter3 = 88 127 | blr_run_max = 89 128 | blr_run_min = 90 129 | blr_run_total = 91 130 | blr_run_average = 92 131 | blr_agg_count2 = 93 132 | blr_agg_count_distinct = 94 133 | blr_agg_total_distinct = 95 134 | blr_agg_average_distinct = 96 135 | blr_function = 100 136 | blr_gen_id = 101 137 | blr_prot_mask = 102 138 | blr_upcase = 103 139 | blr_lock_state = 104 140 | blr_value_if = 105 141 | blr_matching2 = 106 142 | blr_index = 107 143 | blr_ansi_like = 108 144 | blr_seek = 112 145 | 146 | blr_continue = 0 147 | blr_forward = 1 148 | blr_backward = 2 149 | blr_bof_forward = 3 150 | blr_eof_backward = 4 151 | 152 | blr_run_count = 118 153 | blr_rs_stream = 119 154 | blr_exec_proc = 120 155 | blr_procedure = 124 156 | blr_pid = 125 157 | blr_exec_pid = 126 158 | blr_singular = 127 159 | blr_abort = 128 160 | blr_block = 129 161 | blr_error_handler = 130 162 | blr_cast = 131 163 | blr_start_savepoint = 134 164 | blr_end_savepoint = 135 165 | 166 | # Access plan items 167 | blr_plan = 139 168 | blr_merge = 140 169 | blr_join = 141 170 | blr_sequential = 142 171 | blr_navigational = 143 172 | blr_indices = 144 173 | blr_retrieve = 145 174 | 175 | blr_relation2 = 146 176 | blr_rid2 = 147 177 | blr_set_generator = 150 178 | blr_ansi_any = 151 179 | blr_exists = 152 180 | blr_record_version = 154 181 | blr_stall = 155 182 | blr_ansi_all = 158 183 | blr_extract = 159 184 | 185 | # sub parameters for blr_extract 186 | blr_extract_year = 0 187 | blr_extract_month = 1 188 | blr_extract_day = 2 189 | blr_extract_hour = 3 190 | blr_extract_minute = 4 191 | blr_extract_second = 5 192 | blr_extract_weekday = 6 193 | blr_extract_yearday = 7 194 | # Added in IB 2.1 195 | blr_extract_millisecond = 8 196 | blr_extract_week = 9 197 | 198 | blr_current_date = 160 199 | blr_current_timestamp = 161 200 | blr_current_time = 162 201 | 202 | # Those codes reuse BLR code space 203 | blr_post_arg = 163 204 | blr_exec_into = 164 205 | blr_user_savepoint = 165 206 | blr_dcl_cursor = 166 207 | blr_cursor_stmt = 167 208 | blr_current_timestamp2 = 168 209 | blr_current_time2 = 169 210 | blr_agg_list = 170 211 | blr_agg_list_distinct = 171 212 | blr_modify2 = 172 213 | 214 | # IB 1.0 specific BLR 215 | blr_current_role = 174 216 | blr_skip = 175 217 | 218 | # IB 1.5 specific BLR 219 | blr_exec_sql = 176 220 | blr_internal_info = 177 221 | blr_nullsfirst = 178 222 | blr_writelock = 179 223 | blr_nullslast = 180 224 | 225 | # IB 2.0 specific BLR 226 | blr_lowcase = 181 227 | blr_strlen = 182 228 | 229 | # sub parameter for blr_strlen 230 | blr_strlen_bit = 0 231 | blr_strlen_char = 1 232 | blr_strlen_octet = 2 233 | 234 | blr_trim = 183 235 | 236 | # first sub parameter for blr_trim 237 | blr_trim_both = 0 238 | blr_trim_leading = 1 239 | blr_trim_trailing = 2 240 | 241 | # second sub parameter for blr_trim 242 | blr_trim_spaces = 0 243 | blr_trim_characters = 1 244 | 245 | # These codes are actions for user-defined savepoints 246 | 247 | blr_savepoint_set = 0 248 | blr_savepoint_release = 1 249 | blr_savepoint_undo = 2 250 | blr_savepoint_release_single = 3 251 | 252 | # These codes are actions for cursors 253 | 254 | blr_cursor_open = 0 255 | blr_cursor_close = 1 256 | blr_cursor_fetch = 2 257 | 258 | # IB 2.1 specific BLR 259 | 260 | blr_init_variable = 184 261 | blr_recurse = 185 262 | blr_sys_function = 186 263 | 264 | # IB 2.5 specific BLR 265 | 266 | blr_auto_trans = 187 267 | blr_similar = 188 268 | blr_exec_stmt = 189 269 | 270 | # subcodes of blr_exec_stmt 271 | blr_exec_stmt_inputs = 1 # input parameters count 272 | blr_exec_stmt_outputs = 2 # output parameters count 273 | blr_exec_stmt_sql = 3 274 | blr_exec_stmt_proc_block = 4 275 | blr_exec_stmt_data_src = 5 276 | blr_exec_stmt_user = 6 277 | blr_exec_stmt_pwd = 7 278 | blr_exec_stmt_tran = 8 # not implemented yet 279 | blr_exec_stmt_tran_clone = 9 # make transaction parameters equal to current transaction 280 | blr_exec_stmt_privs = 10 281 | blr_exec_stmt_in_params = 11 # not named input parameters 282 | blr_exec_stmt_in_params2 = 12 # named input parameters 283 | blr_exec_stmt_out_params = 13 # output parameters 284 | blr_exec_stmt_role = 14 285 | 286 | blr_stmt_expr = 190 287 | blr_derived_expr = 191 288 | 289 | -------------------------------------------------------------------------------- /interbase/test/README.md: -------------------------------------------------------------------------------- 1 | # How to setup OTW/SSL for tests 2 | 3 | ## Linux: 4 | ### Generating private key with passwords 5 | 6 | 1. To generate a private key with password run: 7 | 8 | ```openssl genrsa -aes256 -out {path}/key.pem 2048``` 9 | 10 | 2. Type your password and verify it when asked. 11 | 3. The output file will be created in dir where you declare in key.pem file. 12 | 13 | ### Requesting a key 14 | 15 | 1. To request a key, on the command line run: 16 | 17 | ```openssl req -new -key {path}/key.pem -out {path}/csr.pem -config openssl.cnf``` 18 | 2. Type the password you set previously. 19 | 3. When asked for information, you don't need to be specific. You can use anything@somewhere.invalid as email because real emails can cause issues. 20 | 4. The file csr.pem is created in the {path} folder. 21 | 22 | ### Signing the key 23 | 24 | 1. To sign the key request file with your private key, on the command line run: 25 | 26 | ```openssl req -x509 -days 3650 -key {path}/key.pem -in {path}/csr.pem -out {path}/ibservercafile.pem``` 27 | 28 | 2. Type the password you set before. 29 | 3. The file ibservercafile.pem is created on the {path} folder. Use this file on your clients. 30 | 31 | ### Creating the server side file 32 | 33 | 1. On the command line, go to the {path} folder. 34 | 2. Add ibservercafile to your private key file. On the command line run: 35 | 36 | ```cat ibservercafile.pem + key.pem > ibserverCAfile.pem``` 37 | 3. Move "ibserverCAfile.pem" file to dir with Interbase Python Driver test/files. 38 | 4. In order to use the server_public_path argument for ssl connection the file should be put into a separate directory and renamed using c_rehash command: 39 | ``` 40 | cd /some/where/certs 41 | c_rehash . 42 | ``` 43 | 44 | ### Configuring InterBase 45 | 46 | 1. Make sure the InterBase server is stopped. 47 | 2. Search for the file ibss_config.default. For example: opt/interBase/secure/server 48 | 3. Open Notepad or other text editor as Administrator. 49 | 4. Type the following text and use the password you set previously: 50 | 51 | ``` 52 | IBSSL_SERVER_PORT_NO=3065 53 | IBSSL_SERVER_CERTFILE="{path to driver}/test/files" 54 | IBSSL_SERVER_PASSPHRASE= 55 | ``` 56 | 57 | This case only for tests! 58 | 59 | 5. Save the file as ibss_config and place it in the same folder as ibss_config.default 60 | 6. Open a text editor as Administrator and open the file `services` located in the `etc` folder. 61 | 7. Add the following line at the bottom: ``` gds_ssl 3065/tcp #InterBase SSL Server```. 62 | 8. Save and close the file. 63 | 9. Start InterBase server. 64 | 65 | ### Starting tests for embedded version of InterBase 66 | 67 | 1. In order to run all unit tests with embedded version of InterBase, 68 | please, uncomment the following line in the file constants.py: 69 | ```# os.environ['IBTEST_USE_EMBEDDED'] = 'True'``` 70 | 71 | ## Windows 72 | 73 | For setup OTW/SSL on Windows you can use: https://docwiki.embarcadero.com/InterBase/2020/en/Setup_OTW/SSL_and_InterBase 74 | 75 | It is important to move `ibserverCAfile.pem` to {path to driver}/test/files folder. 76 | -------------------------------------------------------------------------------- /interbase/test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/interbase/test/__init__.py -------------------------------------------------------------------------------- /interbase/test/constants.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: constants.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | 29 | # Note: since client library is cached (see ibcore.py:29), 30 | # it makes sense to either run all tests as embedded or server 31 | IBTEST_USE_EMBEDDED = False 32 | os.environ['IBTEST_USE_EMBEDDED'] = str(IBTEST_USE_EMBEDDED) 33 | 34 | IBTEST_DB = 'test2020v4.ib' 35 | 36 | # IBTEST_HOST = 'localhost' 37 | # IBTEST_HOST = 'localhost/gds_ssl' 38 | # Best practice tip: It is recommended to have 'gds_ssl' service assigned to port 3065 in your services file. 39 | IBTEST_HOST = None 40 | 41 | IBTEST_USER = 'SYSDBA' 42 | 43 | IBTEST_PASSWORD = 'masterkey' 44 | # Path to dir for test db and temp files 45 | IBTEST_DB_DIR_PATH = os.path.join(os.getcwd(), 'files') 46 | # Full path to test database file 47 | IBTEST_DB_PATH = os.path.join(IBTEST_DB_DIR_PATH, IBTEST_DB) 48 | 49 | # Define the IBTEST_SERVER_PUBLIC_FILE location to enable OTW, Set it to None to disable OTW 50 | # Also remember to set IBTEST_HOST explicitly if OTW is enabled 51 | # IBTEST_SERVER_PUBLIC_FILE = os.path.join(IBTEST_DB_DIR_PATH, "ibserverCAfile.pem") 52 | # IBTEST_SERVER_PUBLIC_FILE = os.path.join(IBTEST_DB_DIR_PATH, "cert") 53 | IBTEST_SERVER_PUBLIC_FILE = None 54 | 55 | IBTEST_SQL_DIALECT = 3 56 | -------------------------------------------------------------------------------- /interbase/test/core.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: core.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import sys 28 | import interbase 29 | import unittest 30 | 31 | from io import StringIO 32 | 33 | 34 | class InterBaseTestBase(unittest.TestCase): 35 | def __init__(self, method_name='runTest'): 36 | super(InterBaseTestBase, self).__init__(method_name) 37 | self.output = StringIO() 38 | 39 | def clear_output(self): 40 | self.output.close() 41 | self.output = StringIO() 42 | 43 | def show_output(self): 44 | sys.stdout.write(self.output.getvalue()) 45 | sys.stdout.flush() 46 | 47 | def printout(self, text='', newline=True): 48 | self.output.write(text) 49 | if newline: 50 | self.output.write('\n') 51 | self.output.flush() 52 | 53 | def printData(self, cur): 54 | """Print data from open cursor to stdout.""" 55 | # Print a header. 56 | for field_desc in cur.description: 57 | self.printout( 58 | field_desc[interbase.DESCRIPTION_NAME].ljust(field_desc[interbase.DESCRIPTION_DISPLAY_SIZE]), 59 | newline=False 60 | ) 61 | self.printout() 62 | for field_desc in cur.description: 63 | self.printout( 64 | "-" * max((len(field_desc[interbase.DESCRIPTION_NAME]), 65 | field_desc[interbase.DESCRIPTION_DISPLAY_SIZE])), 66 | newline=False 67 | ) 68 | self.printout() 69 | # For each row, print the value of each field left-justified within 70 | # the maximum possible width of that field. 71 | field_indices = range(len(cur.description)) 72 | for row in cur: 73 | for fieldIndex in field_indices: 74 | field_value = str(row[fieldIndex]) 75 | field_max_width = max( 76 | ( 77 | len(cur.description[fieldIndex][interbase.DESCRIPTION_NAME]), 78 | cur.description[fieldIndex][interbase.DESCRIPTION_DISPLAY_SIZE] 79 | ) 80 | ) 81 | self.printout(field_value.ljust(field_max_width), newline=False) 82 | self.printout() 83 | 84 | 85 | class SchemaVisitor(interbase.schema.SchemaVisitor): 86 | def __init__(self, test, action, follow='dependencies'): 87 | self.test = test 88 | self.seen = [] 89 | self.action = action 90 | self.follow = follow 91 | 92 | def default_action(self, obj): 93 | if not obj.issystemobject() and self.action in obj.actions: 94 | if self.follow == 'dependencies': 95 | for dependency in obj.get_dependencies(): 96 | d = dependency.depended_on 97 | if d and d not in self.seen: 98 | d.accept_visitor(self) 99 | elif self.follow == 'dependents': 100 | for dependency in obj.get_dependents(): 101 | d = dependency.dependent 102 | if d and d not in self.seen: 103 | d.accept_visitor(self) 104 | if obj not in self.seen: 105 | self.test.printout(obj.get_sql_for(self.action)) 106 | self.seen.append(obj) 107 | 108 | def visitSchema(self, schema): 109 | pass 110 | 111 | def visitMetadataItem(self, item): 112 | pass 113 | 114 | def visitTableColumn(self, column): 115 | column.table.accept_visitor(self) 116 | 117 | def visitViewColumn(self, column): 118 | column.view.accept_visitor(self) 119 | 120 | def visitDependency(self, dependency): 121 | pass 122 | 123 | def visitConstraint(self, constraint): 124 | pass 125 | 126 | def visitProcedureParameter(self, param): 127 | param.procedure.accept_visitor(self) 128 | 129 | def visitFunctionArgument(self, arg): 130 | arg.function.accept_visitor(self) 131 | 132 | def visitDatabaseFile(self, dbfile): 133 | pass 134 | 135 | def visitShadow(self, shadow): 136 | pass 137 | -------------------------------------------------------------------------------- /interbase/test/files/cert/3b307515.0: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDazCCAlOgAwIBAgIUKKu885qDY1HDt4cm/3Qy+ECcxKYwDQYJKoZIhvcNAQEL 3 | BQAwRTELMAkGA1UEBhMCVUExEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAzMDkxMzExMzBaFw0zMzAz 5 | MDYxMzExMzBaMEUxCzAJBgNVBAYTAlVBMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw 6 | HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB 7 | AQUAA4IBDwAwggEKAoIBAQCqNeWOaBhmldITehqRBuZTPWN4I6++2r9fDCga9IDC 8 | uOAFBu8yEfXlctesDpoDPxt3m1AuHlIsxPVUoLFbCNsnTeONFZUY4m+9FcQOW5UL 9 | Qcx748DzuMsMhb04hB69YzDdnCZL6CMGBSdFQPK1MfqdYKR76FeJuOABLOzagVCc 10 | k3wrI04em+Kj0OMGbd2F1CAg/Lpfe1OCevMaZOankxZGKA2/e3A9cXubDgrtgajo 11 | WG0VuyiXI/Xg11/var/4eyA/8bKDo0lUk0P+M2PubdRI5ixU6hqRhjdULLTRyZ4e 12 | VTf7hgsSGWkAi8+GplJiEUGiBIU+8VdPXdvqwCjOWB0pAgMBAAGjUzBRMB0GA1Ud 13 | DgQWBBRI3mCAb2zvD+EFT65ZTKhoVp6W7zAfBgNVHSMEGDAWgBRI3mCAb2zvD+EF 14 | T65ZTKhoVp6W7zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCU 15 | qwoISd0lT368eEabtF/jlEx55YB76HW6c5OvXy1iMUob8QI7e52WT4TToWp8/SC5 16 | 3CbvIpVlAWDgm90ehom+3ABc4qjov3yMiGnIYR3j1E6dIcgVz+6e+3YjmyVHZK7E 17 | QJGPevXU9Kxa90JoV5McbWy37D2CWRPmRZQa1OriSABUD4EXHsBkfXo2u3yl3XUo 18 | noKpNwVvui4CGzLGtUmG3dVjUo14Pnm+EmedTRIZQ+JTXQXWRz4l6f9YzsHsYM7f 19 | iRbquN9pj/LqtfuYVz8EgB0qGtBOmaAtxas9EO2OKkiHJcqhUoW5in0JB6Tq4b2b 20 | qF4AlRjQsZQ9F0unlI0N 21 | -----END CERTIFICATE----- 22 | -----BEGIN ENCRYPTED PRIVATE KEY----- 23 | MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIRQO4IDQpa2YCAggA 24 | MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBC8wJ1uTH2qG3nQ8QoAOmxGBIIE 25 | 0Gg/X4mZfGB4iUUM++N/O2adkAz/5hfchOv1V6TGd3lVgc3y16xYSKXXXNmGgUsM 26 | KAtWaK3dcFXJ3dFFvd34uMjsbKjCZno/A6nS8kWIg4AO7lgafBuRxwVkgYH2Gma2 27 | 4t/julsSProhH2say+o36OxCJN4H50CTkK0Q+nURJQsxOc1TS17FQJPb5Y91pFZG 28 | Hj3VFmhJmpQhIR0+InYV7AhD3PatLKl5wt0ZUS6Kzkd6P0mcq22UQoZ9keB1JbC9 29 | yhsDvxWElpPNbNRmMxbtIF4n5tvkja14vbjfQtrvVuPUL+K3Wiuo/j4+nh9i8D/A 30 | /KqlMonr6I1VRaAuLrUDTlUCrszC8lopL3dn5qpYFfym811jPqbdSNMUCA6ZZUaF 31 | DDXx0nTxCk93cXPIJW2sqIICa/MFVSCwtkbZuirinXlqQVxlTwY+fP2j9Cmju4Ow 32 | dm0rrC2m3MKEyL9I6QVfIeJISCcsCxWoI+/YL0KWK6AFBbYrYw9c3UKrsIHOancL 33 | /9gL+jO/e7NYrQZNOktMCfqhMyqucWvmSdPY+mRzzscLHlzzYUYtR9EylToSR9GG 34 | k2Rvu0PC95uJUF4E9E0oBjNq2Y/IMJTxIWe+qbtmO3wnrDiF+uTS7sxdkQ/7N3p7 35 | 8+oF5KhQHl9H/73ELH+ApSTsQvS4pj3a4rwvohtw0y0eVhi6fnWs1fpUES9GUqn/ 36 | 2jmc/RqpA5G3C8VhhSux8M/j340vASG2uMUKNs5er2hWA1q2w7Y0gvhcZSAS3PxR 37 | QIpEVOgIqnZpx5KDqjFLUqVLiboGsBJ8Dzw64KgwGUpq6SxOGXKdeC4qDXHAXwjN 38 | L8FWpUrAxC62LjigkZEUy1koSJboh7apEe4UOYRIzQyq3MXqdalx0en4edXqZ0nU 39 | 6BzMe353wjiBaLIvBioJJkt264vW9ucJUxIKhR2/Yv5IeOeMCcPdzT0IBVdEuwnh 40 | L2OkOdb/ji1NCoKn+35XueMju7jeVUYndiISTyG3yES4Bnn5HEYpsSwbyBMrh3vj 41 | BAF7TBKzKxFeBzF66wzdjhJiOvDqulMiQN9xjvg2AKuGeh/j023fN9KRgUg354pZ 42 | iEUaqkv9EqsrCEBd2NTVs6AwU13wxvVEG40KmbMkNK9MhqB7LfYjpqVGaMlW6GoI 43 | kLkVI9jcKIvCnFkrF/3Ub8ZrTAYM/QPbiQctumE/phsHhiwQjRlRgB6mKdsQXJP3 44 | bo+YebgBFTmiLDALC8+1jEOxCaX17h/tHy43sfgDcfJoZn5586QmJXn65ExsN7DM 45 | TvAyqyB40uouGGq9i6oHvUr1WaHtyWYDOl56IZSZ8hRUZcH8BfNsG8cgGoJJqRj2 46 | xxjqdzmB0aVdVl8N6GlfjcItwcE9FRAM7BBRHgBet0AN90C+lZJnDbGzkq1EkdaF 47 | S/X/plqUouvSRlb8gwqi5/fm8SdWr0ML5jSAkz2/WF+yB+N30hFaVvEnHgHxAfSV 48 | v3gICycSJ9GMbTU0SD6lNCaVlsahAU/K2Oef5MlUoHu1YzBHjWZ1Zh0tSellLEdU 49 | ECDNvUcI+56qdeKsNtDRfSKJqRg5/G3GqCQU9mmKNx9ZiGiNTRO7s5nyfJALA/FZ 50 | kcDU9s+pr44EvligzahrcmgXzKUq0/2TcHA2vGGh3WmF 51 | -----END ENCRYPTED PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /interbase/test/files/cert/ibserverCAfile.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDazCCAlOgAwIBAgIUKKu885qDY1HDt4cm/3Qy+ECcxKYwDQYJKoZIhvcNAQEL 3 | BQAwRTELMAkGA1UEBhMCVUExEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAzMDkxMzExMzBaFw0zMzAz 5 | MDYxMzExMzBaMEUxCzAJBgNVBAYTAlVBMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw 6 | HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB 7 | AQUAA4IBDwAwggEKAoIBAQCqNeWOaBhmldITehqRBuZTPWN4I6++2r9fDCga9IDC 8 | uOAFBu8yEfXlctesDpoDPxt3m1AuHlIsxPVUoLFbCNsnTeONFZUY4m+9FcQOW5UL 9 | Qcx748DzuMsMhb04hB69YzDdnCZL6CMGBSdFQPK1MfqdYKR76FeJuOABLOzagVCc 10 | k3wrI04em+Kj0OMGbd2F1CAg/Lpfe1OCevMaZOankxZGKA2/e3A9cXubDgrtgajo 11 | WG0VuyiXI/Xg11/var/4eyA/8bKDo0lUk0P+M2PubdRI5ixU6hqRhjdULLTRyZ4e 12 | VTf7hgsSGWkAi8+GplJiEUGiBIU+8VdPXdvqwCjOWB0pAgMBAAGjUzBRMB0GA1Ud 13 | DgQWBBRI3mCAb2zvD+EFT65ZTKhoVp6W7zAfBgNVHSMEGDAWgBRI3mCAb2zvD+EF 14 | T65ZTKhoVp6W7zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCU 15 | qwoISd0lT368eEabtF/jlEx55YB76HW6c5OvXy1iMUob8QI7e52WT4TToWp8/SC5 16 | 3CbvIpVlAWDgm90ehom+3ABc4qjov3yMiGnIYR3j1E6dIcgVz+6e+3YjmyVHZK7E 17 | QJGPevXU9Kxa90JoV5McbWy37D2CWRPmRZQa1OriSABUD4EXHsBkfXo2u3yl3XUo 18 | noKpNwVvui4CGzLGtUmG3dVjUo14Pnm+EmedTRIZQ+JTXQXWRz4l6f9YzsHsYM7f 19 | iRbquN9pj/LqtfuYVz8EgB0qGtBOmaAtxas9EO2OKkiHJcqhUoW5in0JB6Tq4b2b 20 | qF4AlRjQsZQ9F0unlI0N 21 | -----END CERTIFICATE----- 22 | -----BEGIN ENCRYPTED PRIVATE KEY----- 23 | MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIRQO4IDQpa2YCAggA 24 | MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBC8wJ1uTH2qG3nQ8QoAOmxGBIIE 25 | 0Gg/X4mZfGB4iUUM++N/O2adkAz/5hfchOv1V6TGd3lVgc3y16xYSKXXXNmGgUsM 26 | KAtWaK3dcFXJ3dFFvd34uMjsbKjCZno/A6nS8kWIg4AO7lgafBuRxwVkgYH2Gma2 27 | 4t/julsSProhH2say+o36OxCJN4H50CTkK0Q+nURJQsxOc1TS17FQJPb5Y91pFZG 28 | Hj3VFmhJmpQhIR0+InYV7AhD3PatLKl5wt0ZUS6Kzkd6P0mcq22UQoZ9keB1JbC9 29 | yhsDvxWElpPNbNRmMxbtIF4n5tvkja14vbjfQtrvVuPUL+K3Wiuo/j4+nh9i8D/A 30 | /KqlMonr6I1VRaAuLrUDTlUCrszC8lopL3dn5qpYFfym811jPqbdSNMUCA6ZZUaF 31 | DDXx0nTxCk93cXPIJW2sqIICa/MFVSCwtkbZuirinXlqQVxlTwY+fP2j9Cmju4Ow 32 | dm0rrC2m3MKEyL9I6QVfIeJISCcsCxWoI+/YL0KWK6AFBbYrYw9c3UKrsIHOancL 33 | /9gL+jO/e7NYrQZNOktMCfqhMyqucWvmSdPY+mRzzscLHlzzYUYtR9EylToSR9GG 34 | k2Rvu0PC95uJUF4E9E0oBjNq2Y/IMJTxIWe+qbtmO3wnrDiF+uTS7sxdkQ/7N3p7 35 | 8+oF5KhQHl9H/73ELH+ApSTsQvS4pj3a4rwvohtw0y0eVhi6fnWs1fpUES9GUqn/ 36 | 2jmc/RqpA5G3C8VhhSux8M/j340vASG2uMUKNs5er2hWA1q2w7Y0gvhcZSAS3PxR 37 | QIpEVOgIqnZpx5KDqjFLUqVLiboGsBJ8Dzw64KgwGUpq6SxOGXKdeC4qDXHAXwjN 38 | L8FWpUrAxC62LjigkZEUy1koSJboh7apEe4UOYRIzQyq3MXqdalx0en4edXqZ0nU 39 | 6BzMe353wjiBaLIvBioJJkt264vW9ucJUxIKhR2/Yv5IeOeMCcPdzT0IBVdEuwnh 40 | L2OkOdb/ji1NCoKn+35XueMju7jeVUYndiISTyG3yES4Bnn5HEYpsSwbyBMrh3vj 41 | BAF7TBKzKxFeBzF66wzdjhJiOvDqulMiQN9xjvg2AKuGeh/j023fN9KRgUg354pZ 42 | iEUaqkv9EqsrCEBd2NTVs6AwU13wxvVEG40KmbMkNK9MhqB7LfYjpqVGaMlW6GoI 43 | kLkVI9jcKIvCnFkrF/3Ub8ZrTAYM/QPbiQctumE/phsHhiwQjRlRgB6mKdsQXJP3 44 | bo+YebgBFTmiLDALC8+1jEOxCaX17h/tHy43sfgDcfJoZn5586QmJXn65ExsN7DM 45 | TvAyqyB40uouGGq9i6oHvUr1WaHtyWYDOl56IZSZ8hRUZcH8BfNsG8cgGoJJqRj2 46 | xxjqdzmB0aVdVl8N6GlfjcItwcE9FRAM7BBRHgBet0AN90C+lZJnDbGzkq1EkdaF 47 | S/X/plqUouvSRlb8gwqi5/fm8SdWr0ML5jSAkz2/WF+yB+N30hFaVvEnHgHxAfSV 48 | v3gICycSJ9GMbTU0SD6lNCaVlsahAU/K2Oef5MlUoHu1YzBHjWZ1Zh0tSellLEdU 49 | ECDNvUcI+56qdeKsNtDRfSKJqRg5/G3GqCQU9mmKNx9ZiGiNTRO7s5nyfJALA/FZ 50 | kcDU9s+pr44EvligzahrcmgXzKUq0/2TcHA2vGGh3WmF 51 | -----END ENCRYPTED PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /interbase/test/files/create-test-db-dialect-1.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | rm -f test2020v4.ib 3 | isql -i create-test-db-dialect-1.sql 4 | -------------------------------------------------------------------------------- /interbase/test/files/create-test-db.bat: -------------------------------------------------------------------------------- 1 | del test2020v4.ib 2 | "C:\Program Files\Embarcadero\InterBase\bin\isql" -i create-test-db.sql 3 | -------------------------------------------------------------------------------- /interbase/test/files/create-test-db.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | rm -f test2020v4.ib 3 | isql -i create-test-db.sql 4 | -------------------------------------------------------------------------------- /interbase/test/files/ibserverCAfile.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDazCCAlOgAwIBAgIUKKu885qDY1HDt4cm/3Qy+ECcxKYwDQYJKoZIhvcNAQEL 3 | BQAwRTELMAkGA1UEBhMCVUExEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM 4 | GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMzAzMDkxMzExMzBaFw0zMzAz 5 | MDYxMzExMzBaMEUxCzAJBgNVBAYTAlVBMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw 6 | HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB 7 | AQUAA4IBDwAwggEKAoIBAQCqNeWOaBhmldITehqRBuZTPWN4I6++2r9fDCga9IDC 8 | uOAFBu8yEfXlctesDpoDPxt3m1AuHlIsxPVUoLFbCNsnTeONFZUY4m+9FcQOW5UL 9 | Qcx748DzuMsMhb04hB69YzDdnCZL6CMGBSdFQPK1MfqdYKR76FeJuOABLOzagVCc 10 | k3wrI04em+Kj0OMGbd2F1CAg/Lpfe1OCevMaZOankxZGKA2/e3A9cXubDgrtgajo 11 | WG0VuyiXI/Xg11/var/4eyA/8bKDo0lUk0P+M2PubdRI5ixU6hqRhjdULLTRyZ4e 12 | VTf7hgsSGWkAi8+GplJiEUGiBIU+8VdPXdvqwCjOWB0pAgMBAAGjUzBRMB0GA1Ud 13 | DgQWBBRI3mCAb2zvD+EFT65ZTKhoVp6W7zAfBgNVHSMEGDAWgBRI3mCAb2zvD+EF 14 | T65ZTKhoVp6W7zAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQCU 15 | qwoISd0lT368eEabtF/jlEx55YB76HW6c5OvXy1iMUob8QI7e52WT4TToWp8/SC5 16 | 3CbvIpVlAWDgm90ehom+3ABc4qjov3yMiGnIYR3j1E6dIcgVz+6e+3YjmyVHZK7E 17 | QJGPevXU9Kxa90JoV5McbWy37D2CWRPmRZQa1OriSABUD4EXHsBkfXo2u3yl3XUo 18 | noKpNwVvui4CGzLGtUmG3dVjUo14Pnm+EmedTRIZQ+JTXQXWRz4l6f9YzsHsYM7f 19 | iRbquN9pj/LqtfuYVz8EgB0qGtBOmaAtxas9EO2OKkiHJcqhUoW5in0JB6Tq4b2b 20 | qF4AlRjQsZQ9F0unlI0N 21 | -----END CERTIFICATE----- 22 | -----BEGIN ENCRYPTED PRIVATE KEY----- 23 | MIIFLTBXBgkqhkiG9w0BBQ0wSjApBgkqhkiG9w0BBQwwHAQIRQO4IDQpa2YCAggA 24 | MAwGCCqGSIb3DQIJBQAwHQYJYIZIAWUDBAEqBBC8wJ1uTH2qG3nQ8QoAOmxGBIIE 25 | 0Gg/X4mZfGB4iUUM++N/O2adkAz/5hfchOv1V6TGd3lVgc3y16xYSKXXXNmGgUsM 26 | KAtWaK3dcFXJ3dFFvd34uMjsbKjCZno/A6nS8kWIg4AO7lgafBuRxwVkgYH2Gma2 27 | 4t/julsSProhH2say+o36OxCJN4H50CTkK0Q+nURJQsxOc1TS17FQJPb5Y91pFZG 28 | Hj3VFmhJmpQhIR0+InYV7AhD3PatLKl5wt0ZUS6Kzkd6P0mcq22UQoZ9keB1JbC9 29 | yhsDvxWElpPNbNRmMxbtIF4n5tvkja14vbjfQtrvVuPUL+K3Wiuo/j4+nh9i8D/A 30 | /KqlMonr6I1VRaAuLrUDTlUCrszC8lopL3dn5qpYFfym811jPqbdSNMUCA6ZZUaF 31 | DDXx0nTxCk93cXPIJW2sqIICa/MFVSCwtkbZuirinXlqQVxlTwY+fP2j9Cmju4Ow 32 | dm0rrC2m3MKEyL9I6QVfIeJISCcsCxWoI+/YL0KWK6AFBbYrYw9c3UKrsIHOancL 33 | /9gL+jO/e7NYrQZNOktMCfqhMyqucWvmSdPY+mRzzscLHlzzYUYtR9EylToSR9GG 34 | k2Rvu0PC95uJUF4E9E0oBjNq2Y/IMJTxIWe+qbtmO3wnrDiF+uTS7sxdkQ/7N3p7 35 | 8+oF5KhQHl9H/73ELH+ApSTsQvS4pj3a4rwvohtw0y0eVhi6fnWs1fpUES9GUqn/ 36 | 2jmc/RqpA5G3C8VhhSux8M/j340vASG2uMUKNs5er2hWA1q2w7Y0gvhcZSAS3PxR 37 | QIpEVOgIqnZpx5KDqjFLUqVLiboGsBJ8Dzw64KgwGUpq6SxOGXKdeC4qDXHAXwjN 38 | L8FWpUrAxC62LjigkZEUy1koSJboh7apEe4UOYRIzQyq3MXqdalx0en4edXqZ0nU 39 | 6BzMe353wjiBaLIvBioJJkt264vW9ucJUxIKhR2/Yv5IeOeMCcPdzT0IBVdEuwnh 40 | L2OkOdb/ji1NCoKn+35XueMju7jeVUYndiISTyG3yES4Bnn5HEYpsSwbyBMrh3vj 41 | BAF7TBKzKxFeBzF66wzdjhJiOvDqulMiQN9xjvg2AKuGeh/j023fN9KRgUg354pZ 42 | iEUaqkv9EqsrCEBd2NTVs6AwU13wxvVEG40KmbMkNK9MhqB7LfYjpqVGaMlW6GoI 43 | kLkVI9jcKIvCnFkrF/3Ub8ZrTAYM/QPbiQctumE/phsHhiwQjRlRgB6mKdsQXJP3 44 | bo+YebgBFTmiLDALC8+1jEOxCaX17h/tHy43sfgDcfJoZn5586QmJXn65ExsN7DM 45 | TvAyqyB40uouGGq9i6oHvUr1WaHtyWYDOl56IZSZ8hRUZcH8BfNsG8cgGoJJqRj2 46 | xxjqdzmB0aVdVl8N6GlfjcItwcE9FRAM7BBRHgBet0AN90C+lZJnDbGzkq1EkdaF 47 | S/X/plqUouvSRlb8gwqi5/fm8SdWr0ML5jSAkz2/WF+yB+N30hFaVvEnHgHxAfSV 48 | v3gICycSJ9GMbTU0SD6lNCaVlsahAU/K2Oef5MlUoHu1YzBHjWZ1Zh0tSellLEdU 49 | ECDNvUcI+56qdeKsNtDRfSKJqRg5/G3GqCQU9mmKNx9ZiGiNTRO7s5nyfJALA/FZ 50 | kcDU9s+pr44EvligzahrcmgXzKUq0/2TcHA2vGGh3WmF 51 | -----END ENCRYPTED PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /interbase/test/files/isql.sh: -------------------------------------------------------------------------------- 1 | isql ./test2020v4.ib -u sysdba -p masterkey 2 | -------------------------------------------------------------------------------- /interbase/test/test_bugs.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_bugs.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | import interbase 29 | import datetime 30 | 31 | from io import BytesIO 32 | from .core import InterBaseTestBase 33 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_DIR_PATH, IBTEST_DB_PATH,\ 34 | IBTEST_SQL_DIALECT, IBTEST_SERVER_PUBLIC_FILE 35 | 36 | 37 | class TestBugs(InterBaseTestBase): 38 | def setUp(self): 39 | self.dbfile = os.path.join(IBTEST_DB_DIR_PATH, 'ibbugs.ib') 40 | if os.path.exists(self.dbfile): 41 | os.remove(self.dbfile) 42 | self.con = interbase.create_database( 43 | host=IBTEST_HOST, 44 | database=self.dbfile, 45 | user=IBTEST_USER, 46 | password=IBTEST_PASSWORD, 47 | sql_dialect=IBTEST_SQL_DIALECT, 48 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 49 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 50 | ) 51 | 52 | def tearDown(self): 53 | self.con.drop_database() 54 | self.con.close() 55 | 56 | def test_pyib_17(self): 57 | create_table = """ 58 | Create Table table1 ( 59 | ID Integer, 60 | C1 Integer NOT Null 61 | ); 62 | """ 63 | # removed "OR UPDATE POSITION 0" because "Token unknown - line 3, char 30\n- OR" 64 | create_trigger = """ 65 | CREATE TRIGGER BIU_Trigger FOR table1 66 | ACTIVE BEFORE INSERT 67 | AS 68 | BEGIN 69 | if (new.C1 IS NULL) then 70 | begin 71 | new.C1 = 1; 72 | end 73 | END 74 | """ 75 | 76 | cur = self.con.cursor() 77 | cur.execute(create_table) 78 | cur.execute(create_trigger) 79 | self.con.commit() 80 | cur.execute('insert into table1 (ID, C1) values(1, ?)', (None,)) 81 | 82 | def test_pyib_22(self): 83 | create_table = """ 84 | CREATE TABLE IBTEST ( 85 | ID INTEGER, 86 | TEST80 VARCHAR(80), 87 | TEST128 VARCHAR(128), 88 | TEST255 VARCHAR(255), 89 | TEST1024 VARCHAR(1024), 90 | TESTCLOB BLOB SUB_TYPE 1 SEGMENT SIZE 255 91 | ); 92 | """ 93 | cur = self.con.cursor() 94 | cur.execute(create_table) 95 | self.con.commit() 96 | # test data 97 | data = ("1234567890" * 25) + "12345" 98 | for i in interbase.ibase.xrange(255): 99 | cur.execute( 100 | "insert into ibtest (id, test255) values (?, ?)", 101 | (i, data[:i]) 102 | ) 103 | self.con.commit() 104 | cur.execute("select test255 from ibtest order by id") 105 | i = 0 106 | for row in cur: 107 | value = row[0] 108 | self.assertEqual(len(value), i) 109 | self.assertEqual(value, data[:i]) 110 | i += 1 111 | 112 | def test_pyib_25(self): 113 | create_table = """ 114 | CREATE TABLE IBTEST2 ( 115 | ID INTEGER, 116 | TEST5000 VARCHAR(5000) 117 | ); 118 | """ 119 | cur = self.con.cursor() 120 | cur.execute(create_table) 121 | self.con.commit() 122 | # test data 123 | data = "1234567890" * 500 124 | cur.execute( 125 | "insert into ibtest2 (id, test5000) values (?, ?)", 126 | (1, data) 127 | ) 128 | self.con.commit() 129 | cur.execute("select test5000 from ibtest2") 130 | row = cur.fetchone() 131 | self.assertEqual(row[0], data) 132 | 133 | def test_pyib_30(self): 134 | create_table = """ 135 | CREATE TABLE IBTEST3 ( 136 | ID INTEGER, 137 | T_BLOB BLOB sub_type 2 138 | ); 139 | """ 140 | cur = self.con.cursor() 141 | cur.execute(create_table) 142 | self.con.commit() 143 | 144 | # test data 145 | data_bytes = (1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9) 146 | blob_data = interbase.bs(data_bytes) 147 | cur.execute( 148 | "insert into ibtest3 (id, t_blob) values (?, ?)", 149 | (1, blob_data) 150 | ) 151 | cur.execute( 152 | "insert into ibtest3 (id, t_blob) values (?, ?)", 153 | (2, BytesIO(blob_data)) 154 | ) 155 | self.con.commit() 156 | 157 | # PYFB-XX: binary blob trucated at zero-byte 158 | cur.execute("select t_blob from ibtest3 where id = 1") 159 | row = cur.fetchone() 160 | self.assertEqual(row[0], blob_data) 161 | 162 | cur.execute("select t_blob from ibtest3 where id = 2") 163 | row = cur.fetchone() 164 | self.assertEqual(row[0], blob_data) 165 | 166 | p = cur.prep("select t_blob from ibtest3 where id = 2") 167 | p.set_stream_blob('T_BLOB') 168 | cur.execute(p) 169 | blob_reader = cur.fetchone()[0] 170 | value = blob_reader.read() 171 | self.assertEqual(value, blob_data) 172 | 173 | def test_pyib_34(self): 174 | cur = self.con.cursor() 175 | cur.execute("select * from RDB$Relations") 176 | cur.fetchall() 177 | del cur 178 | 179 | def test_pyib_35(self): 180 | create_table = """ 181 | Create Table table1 ( 182 | ID Integer, 183 | C1 Integer NOT Null 184 | ); 185 | """ 186 | 187 | c = self.con.cursor() 188 | c.execute(create_table) 189 | self.con.commit() 190 | del c 191 | 192 | cur = self.con.cursor() 193 | with self.assertRaises(interbase.DatabaseError) as cm: 194 | cur.fetchall() 195 | self.assertTupleEqual( 196 | cm.exception.args, 197 | ("Cannot fetch from this cursor because it has not executed a statement.",) 198 | ) 199 | 200 | cur.execute("select * from RDB$DATABASE") 201 | cur.fetchall() 202 | cur.execute("create generator seqtest") 203 | with self.assertRaises(interbase.DatabaseError) as cm: 204 | cur.fetchall() 205 | self.assertTupleEqual( 206 | cm.exception.args, 207 | ("Attempt to fetch row of results after statement that does not produce result set.",) 208 | ) 209 | 210 | def test_pyib_44(self): 211 | self.con2 = interbase.connect( 212 | host=IBTEST_HOST, 213 | database=IBTEST_DB_PATH, 214 | user=IBTEST_USER, 215 | password=IBTEST_PASSWORD, 216 | sql_dialect=IBTEST_SQL_DIALECT, 217 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 218 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 219 | ) 220 | try: 221 | cur = self.con2.cursor() 222 | now = datetime.datetime(2011, 11, 13, 15, 00, 1, 200) 223 | cur.execute('insert into T2 (C1,C8) values (?,?)', [3, now.date()]) 224 | self.con2.commit() 225 | cur.execute('select C1,C8 from T2 where C1 = 3') 226 | rows = cur.fetchall() 227 | self.assertListEqual( 228 | rows, 229 | [(3, datetime.datetime(2011, 11, 13, 0, 0, 0, 0))] 230 | ) 231 | finally: 232 | self.con2.execute_immediate("delete from t2") 233 | self.con2.commit() 234 | self.con2.close() 235 | -------------------------------------------------------------------------------- /interbase/test/test_change_views.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_change_views.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | import interbase 29 | import time 30 | 31 | from .core import InterBaseTestBase 32 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_PATH, IBTEST_SQL_DIALECT,\ 33 | IBTEST_SERVER_PUBLIC_FILE 34 | 35 | 36 | class TestChangeView(InterBaseTestBase): 37 | def setUp(self): 38 | self.cwd = os.getcwd() 39 | self.dbpath = os.path.join(self.cwd, "test") 40 | self.dbfile = os.path.join(self.dbpath, IBTEST_DB_PATH) 41 | self.con = interbase.connect( 42 | host=IBTEST_HOST, 43 | database=self.dbfile, 44 | user=IBTEST_USER, 45 | password=IBTEST_PASSWORD, 46 | isolation_level=interbase.ISOLATION_LEVEL_SERIALIZABLE, 47 | sql_dialect=IBTEST_SQL_DIALECT, 48 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 49 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 50 | ) 51 | 52 | def test_table_subscription(self): 53 | cur = self.con.cursor() 54 | cur.execute( 55 | "CREATE TABLE CUSTOMER2 (" 56 | "CUST_NO INTEGER NOT NULL," 57 | "CUSTOMER VARCHAR(25)," 58 | "CONSTRAINT RDB$PRIMARY2503 PRIMARY KEY(CUST_NO))" 59 | ) 60 | self.con.commit() 61 | 62 | original_values = ((1, "first dummy string"), (2, "second dummy string")) 63 | for row in original_values: 64 | statement = f"INSERT INTO CUSTOMER2 (CUST_NO, CUSTOMER) VALUES ({row[0]}, '{row[1]}')" 65 | cur.execute(statement) 66 | self.con.commit() 67 | 68 | cur.execute( 69 | "CREATE SUBSCRIPTION SUB_CUSTOMER2_CHANGE ON CUSTOMER2 (CUST_NO, CUSTOMER)" 70 | "FOR ROW (INSERT, UPDATE, DELETE)" 71 | ) 72 | cur.execute( 73 | f"GRANT SUBSCRIBE ON SUBSCRIPTION SUB_CUSTOMER2_CHANGE to {IBTEST_USER}" 74 | ) 75 | self.con.execute_immediate("SET SUBSCRIPTION SUB_CUSTOMER2_CHANGE ACTIVE") 76 | self.con.commit() 77 | 78 | inserted_record = (3, "inserted string") 79 | statement = f"INSERT INTO CUSTOMER2 (CUST_NO, CUSTOMER) VALUES ({inserted_record[0]}, '{inserted_record[1]}')" 80 | self.con.execute_immediate(statement) 81 | self.con.commit() 82 | 83 | new_customer_string = "new dummy string" 84 | self.con.execute_immediate( 85 | f"UPDATE CUSTOMER2 SET CUSTOMER='{new_customer_string}' WHERE CUST_NO=2" 86 | ) 87 | self.con.commit() 88 | 89 | deleted_record_id = 1 90 | statement = f"DELETE FROM CUSTOMER2 WHERE CUST_NO = {deleted_record_id}" 91 | self.con.execute_immediate(statement) 92 | self.con.commit() 93 | 94 | time.sleep(1) # last operation takes time to appear in change_view? 95 | 96 | self.con.execute_immediate("SET SUBSCRIPTION SUB_CUSTOMER2_CHANGE ACTIVE") 97 | cur = self.con.cursor() 98 | statement = cur.prep("SELECT * FROM CUSTOMER2") 99 | cur.execute(statement) 100 | changed_records = cur.fetchall() 101 | 102 | statement.close() 103 | self.con.commit() 104 | self.con.close() 105 | 106 | changed_records.sort() 107 | 108 | deleted_record = changed_records[0] 109 | updated_record = changed_records[1] 110 | inserted_record = changed_records[2] 111 | 112 | assert updated_record[1][1] & interbase.SQLIND_UPDATE 113 | assert inserted_record[1][1] & interbase.SQLIND_INSERT 114 | assert deleted_record[1][1] & interbase.SQLIND_DELETE 115 | assert len(changed_records) == 3 116 | 117 | def tearDown(self): 118 | self.con = interbase.connect( 119 | host=IBTEST_HOST, 120 | database=self.dbfile, 121 | user=IBTEST_USER, 122 | password=IBTEST_PASSWORD, 123 | sql_dialect=IBTEST_SQL_DIALECT, 124 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 125 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 126 | ) 127 | self.con.execute_immediate("DROP SUBSCRIPTION SUB_CUSTOMER2_CHANGE CASCADE") 128 | self.con.commit() 129 | self.con.execute_immediate("DROP TABLE CUSTOMER2") 130 | self.con.commit() 131 | self.con.close() 132 | -------------------------------------------------------------------------------- /interbase/test/test_charset_conversion.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_charset_conversion.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import interbase 28 | 29 | from .core import InterBaseTestBase 30 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_PATH, IBTEST_SQL_DIALECT,\ 31 | IBTEST_SERVER_PUBLIC_FILE 32 | 33 | 34 | class TestCharsetConversion(InterBaseTestBase): 35 | def setUp(self): 36 | self.con = interbase.connect( 37 | host=IBTEST_HOST, 38 | database=IBTEST_DB_PATH, 39 | user=IBTEST_USER, 40 | password=IBTEST_PASSWORD, 41 | charset='utf8', 42 | sql_dialect=IBTEST_SQL_DIALECT, 43 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 44 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 45 | ) 46 | 47 | def tearDown(self): 48 | self.con.execute_immediate("delete from t3") 49 | self.con.execute_immediate("delete from t4") 50 | self.con.commit() 51 | self.con.close() 52 | 53 | def test_octets(self): 54 | bytestring = interbase.ibcore.bs([1, 2, 3, 4, 5]) 55 | cur = self.con.cursor() 56 | cur.execute("insert into T4 (C1, C_OCTETS, V_OCTETS) values (?,?,?)", 57 | (1, bytestring, bytestring)) 58 | self.con.commit() 59 | cur.execute("select C1, C_OCTETS, V_OCTETS from T4 where C1 = 1") 60 | row = cur.fetchone() 61 | self.assertTupleEqual( 62 | row, 63 | (1, b'\x01\x02\x03\x04\x05', b'\x01\x02\x03\x04\x05') 64 | ) 65 | 66 | def test_utf82win1250(self): 67 | str_5utf8 = 'ěščřž' 68 | str_30utf8 = 'ěščřžýáíéúůďťňóĚŠČŘŽÝÁÍÉÚŮĎŤŇÓ' 69 | str_5win1250 = 'abcde' 70 | str_30win1250 = '012345678901234567890123456789' 71 | 72 | con1250 = interbase.connect( 73 | host=IBTEST_HOST, 74 | database=IBTEST_DB_PATH, 75 | user=IBTEST_USER, 76 | password=IBTEST_PASSWORD, 77 | charset='win1250', 78 | sql_dialect=IBTEST_SQL_DIALECT, 79 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 80 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 81 | ) 82 | c_utf8 = self.con.cursor() 83 | c_win1250 = con1250.cursor() 84 | 85 | # Insert unicode data 86 | c_utf8.execute("insert into T4 (C1, C_WIN1250, V_WIN1250, C_UTF8, V_UTF8) values (?,?,?,?,?)", 87 | (1, str_5win1250, str_30win1250, str_5utf8, str_30utf8)) 88 | self.con.commit() 89 | 90 | # Should return the same unicode content when read from win1250 or utf8 connection 91 | c_win1250.execute("select C1, C_WIN1250, V_WIN1250," 92 | "C_UTF8, V_UTF8 from T4 where C1 = 1") 93 | row = c_win1250.fetchone() 94 | self.assertTupleEqual(row, (1, str_5win1250, str_30win1250, str_5utf8, str_30utf8)) 95 | c_utf8.execute("select C1, C_WIN1250, V_WIN1250," 96 | "C_UTF8, V_UTF8 from T4 where C1 = 1") 97 | row = c_utf8.fetchone() 98 | self.assertTupleEqual(row, (1, str_5win1250, str_30win1250, str_5utf8, str_30utf8)) 99 | 100 | def testCharVarchar(self): 101 | s = 'Introdução' 102 | self.assertEqual(len(s), 10) 103 | data = tuple([1, s, s]) 104 | cur = self.con.cursor() 105 | cur.execute('insert into T3 (C1,C2,C3) values (?,?,?)', data) 106 | self.con.commit() 107 | cur.execute('select C1,C2,C3 from T3 where C1 = 1') 108 | row = cur.fetchone() 109 | self.assertEqual(row, data) 110 | 111 | def testBlob(self): 112 | s = """Introdução 113 | 114 | Este artigo descreve como você pode fazer o InterBase e o InterBase 1.5 115 | coehabitarem pacificamente seu computador Windows. Por favor, note que esta 116 | solução não permitirá que o InterBase e o InterBase rodem ao mesmo tempo. 117 | Porém você poderá trocar entre ambos com um mínimo de luta. """ 118 | self.assertEqual(len(s), 294) 119 | data = tuple([2, s]) 120 | b_data = tuple([3, interbase.ibase.b('bytestring')]) 121 | cur = self.con.cursor() 122 | # Text BLOB 123 | cur.execute('insert into T3 (C1,C4) values (?,?)', data) 124 | self.con.commit() 125 | cur.execute('select C1,C4 from T3 where C1 = 2') 126 | row = cur.fetchone() 127 | self.assertEqual(row, data) 128 | # Insert Unicode into non-textual BLOB 129 | with self.assertRaises(TypeError) as cm: 130 | cur.execute('insert into T3 (C1,C5) values (?,?)', data) 131 | self.con.commit() 132 | self.assertTupleEqual( 133 | cm.exception.args, 134 | ('Unicode strings are not acceptable input for a non-textual BLOB column.',) 135 | ) 136 | # Read binary from non-textual BLOB 137 | cur.execute('insert into T3 (C1,C5) values (?,?)', b_data) 138 | self.con.commit() 139 | cur.execute('select C1,C5 from T3 where C1 = 3') 140 | row = cur.fetchone() 141 | self.assertEqual(row, b_data) 142 | -------------------------------------------------------------------------------- /interbase/test/test_create.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_bugs.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | import interbase 29 | 30 | from .core import InterBaseTestBase 31 | from contextlib import closing 32 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_DIR_PATH,\ 33 | IBTEST_SQL_DIALECT, IBTEST_SERVER_PUBLIC_FILE 34 | 35 | 36 | class TestCreateDrop(InterBaseTestBase): 37 | def setUp(self): 38 | self.db_file = os.path.join(IBTEST_DB_DIR_PATH, 'droptest.ib') 39 | if os.path.exists(self.db_file): 40 | os.remove(self.db_file) 41 | 42 | def test_create_drop(self): 43 | with closing(interbase.create_database( 44 | host=IBTEST_HOST, 45 | database=self.db_file, 46 | user=IBTEST_USER, password=IBTEST_PASSWORD, 47 | sql_dialect=IBTEST_SQL_DIALECT, 48 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 49 | server_public_file=IBTEST_SERVER_PUBLIC_FILE) 50 | ) as con: 51 | con.drop_database() 52 | -------------------------------------------------------------------------------- /interbase/test/test_encryption.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_encryption.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | import interbase 29 | import time 30 | 31 | from .core import InterBaseTestBase 32 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_DIR_PATH, \ 33 | IBTEST_SQL_DIALECT, IBTEST_SERVER_PUBLIC_FILE 34 | 35 | 36 | class TestEncryption(InterBaseTestBase): 37 | def setUp(self) -> None: 38 | self.test_db_path = os.path.join(IBTEST_DB_DIR_PATH, "encrypt.ib") 39 | self.backup_file = os.path.join(IBTEST_DB_DIR_PATH, "backup.ib") 40 | self.encrypt_key = "test_key" 41 | self.protecred_enc_key = "protected_key" 42 | self.test_username, self.test_password = 'TEST_USER', 'masterkey' 43 | 44 | self.user_connection = None 45 | self.sysdba_connection = None 46 | self.sysdso_connection = None 47 | 48 | if os.path.exists(self.test_db_path): 49 | os.remove(self.test_db_path) 50 | 51 | self.sysdba_connection: interbase.Connection = interbase.create_database( 52 | host=IBTEST_HOST, 53 | database=self.test_db_path, 54 | user=IBTEST_USER, 55 | password=IBTEST_PASSWORD, 56 | sql_dialect=IBTEST_SQL_DIALECT, 57 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 58 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 59 | ) 60 | self.sysdba_connection.execute_immediate("""CREATE USER SYSDSO SET PASSWORD '%s'""" % self.test_password) 61 | self.sysdba_connection.execute_immediate( 62 | """CREATE USER %s SET PASSWORD '%s'""" % (self.test_username, self.test_password) 63 | ) 64 | self.sysdba_connection.execute_immediate( 65 | """CREATE USER %s SET PASSWORD '%s'""" % ('TEST_USER_2', 'TEST') 66 | ) 67 | self.sysdba_connection.commit() 68 | 69 | self.sysdso_connection: interbase.Connection = interbase.connect( 70 | user='SYSDSO', 71 | password=self.test_password, 72 | database=self.test_db_path, 73 | sql_dialect=IBTEST_SQL_DIALECT, 74 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 75 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 76 | ) 77 | self.user_connection: interbase.Connection = interbase.connect( 78 | user=self.test_username, 79 | password=self.test_password, 80 | database=self.test_db_path, 81 | sql_dialect=IBTEST_SQL_DIALECT, 82 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 83 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 84 | ) 85 | 86 | self.sysdso_connection.execute_immediate("""ALTER DATABASE SET SYSTEM ENCRYPTION PASSWORD 'masterkey'""") 87 | self.sysdso_connection.execute_immediate("""CREATE ENCRYPTION %s FOR AES""" % self.encrypt_key) 88 | self.sysdso_connection.execute_immediate( 89 | """CREATE ENCRYPTION %s FOR AES PASSWORD 'masterkey'""" % self.protecred_enc_key 90 | ) 91 | self.sysdso_connection.commit() 92 | 93 | def tearDown(self) -> None: 94 | self.sysdso_connection.close() 95 | self.user_connection.close() 96 | self.sysdba_connection.close() 97 | time.sleep(1) # wait for the client lib to release the db file 98 | 99 | if os.path.exists(self.test_db_path): 100 | os.remove(self.test_db_path) 101 | 102 | if os.path.exists(self.backup_file): 103 | os.remove(self.backup_file) 104 | 105 | def test_encrypt_backup(self): 106 | with interbase.services.connect( 107 | host=IBTEST_HOST, 108 | user=IBTEST_USER, 109 | password=IBTEST_PASSWORD, 110 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 111 | server_public_file=IBTEST_SERVER_PUBLIC_FILE, 112 | ) as service: 113 | service.backup( 114 | self.test_db_path, 115 | self.backup_file, 116 | sep_password="masterkey", 117 | encrypt_name=self.protecred_enc_key 118 | ) 119 | self.assertTrue(os.path.exists(self.backup_file)) 120 | service.wait() 121 | service.restore( 122 | self.backup_file, 123 | self.test_db_path, 124 | replace=1, 125 | sep_password="masterkey", 126 | decrypt_password="masterkey", 127 | ) 128 | 129 | def test_encrypt_database(self): 130 | self.sysdso_connection.execute_immediate( 131 | """GRANT ENCRYPT ON ENCRYPTION %s TO SYSDBA""" % self.encrypt_key 132 | ) 133 | self.sysdso_connection.commit() 134 | 135 | sysdba_cursor = self.sysdba_connection.cursor() 136 | sysdba_cursor.execute("""ALTER DATABASE ENCRYPT with %s""" % self.encrypt_key) 137 | self.sysdba_connection.commit() 138 | 139 | with self.assertRaises(interbase.ibcore.DatabaseError): 140 | # should raise exception because database is already encrypted 141 | sysdba_cursor.execute("""ALTER DATABASE ENCRYPT with %s""" % self.encrypt_key) 142 | 143 | conn: interbase.Connection = interbase.connect( 144 | dsn=self.test_db_path, 145 | user='TEST_USER_2', 146 | password='TEST', 147 | sql_dialect=IBTEST_SQL_DIALECT, 148 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 149 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 150 | ) 151 | cursor = conn.cursor() 152 | cursor.execute("CREATE TABLE v_table (number INTEGER)") 153 | conn.commit() 154 | conn.close() 155 | 156 | def test_encryption(self): 157 | self.sysdso_connection.execute_immediate( 158 | """CREATE TABLE user_table (number INTEGER ENCRYPT with %s decrypt default 10)""" % self.encrypt_key 159 | ) 160 | self.sysdso_connection.commit() 161 | 162 | self.sysdso_connection.execute_immediate( 163 | """ALTER TABLE user_table ADD total_value INTEGER ENCRYPT with test_key""" 164 | ) 165 | self.sysdso_connection.commit() 166 | 167 | self.sysdso_connection.execute_immediate( 168 | """CREATE TABLE test_table (number INTEGER ENCRYPT with test_key decrypt default 10)""" 169 | ) 170 | self.sysdso_connection.execute_immediate( 171 | """GRANT INSERT, SELECT, DECRYPT (number) ON test_table TO %s""" % self.test_username 172 | ) 173 | self.sysdso_connection.commit() 174 | 175 | self.user_connection.execute_immediate("""INSERT INTO test_table (number) VALUES (90)""") 176 | self.user_connection.execute_immediate("""INSERT INTO test_table (number) VALUES (15)""") 177 | self.user_connection.execute_immediate("""INSERT INTO test_table (number) VALUES (30)""") 178 | self.user_connection.commit() 179 | 180 | cursor = self.user_connection.cursor() 181 | cursor.execute("SELECT * FROM test_table") 182 | data = cursor.fetchall() 183 | 184 | self.assertEqual(len(data), 3) 185 | 186 | self.sysdso_connection.execute_immediate("""GRANT ENCRYPT ON ENCRYPTION test_key to SYSDBA;""") 187 | self.sysdso_connection.commit() 188 | 189 | self.sysdba_connection.execute_immediate( 190 | """CREATE TABLE T4 (number INTEGER ENCRYPT WITH test_key DECRYPT DEFAULT 10);""" 191 | ) 192 | self.sysdba_connection.execute_immediate( 193 | """GRANT INSERT, SELECT ON TABLE T4 to %s;""" % self.test_username 194 | ) 195 | self.sysdba_connection.commit() 196 | 197 | self.user_connection.execute_immediate("""INSERT INTO T4 (number) VALUES (77)""") 198 | self.user_connection.commit() 199 | 200 | user_cursor = self.user_connection.cursor() 201 | user_cursor.execute("SELECT * FROM T4") 202 | data = user_cursor.fetchone() 203 | self.assertEqual(data[0], 77) 204 | user_cursor.close() 205 | -------------------------------------------------------------------------------- /interbase/test/test_events.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_events.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | import interbase 29 | import time 30 | import threading 31 | 32 | from unittest import skip 33 | from .core import InterBaseTestBase 34 | from .constants import IBTEST_DB_DIR_PATH, IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_SQL_DIALECT,\ 35 | IBTEST_SERVER_PUBLIC_FILE 36 | 37 | 38 | class TestEvents(InterBaseTestBase): 39 | def setUp(self): 40 | self.dbfile = os.path.join(IBTEST_DB_DIR_PATH, 'ibevents.ib') 41 | if os.path.exists(self.dbfile): 42 | os.remove(self.dbfile) 43 | self.con = interbase.create_database( 44 | host=IBTEST_HOST, 45 | database=self.dbfile, 46 | user=IBTEST_USER, 47 | password=IBTEST_PASSWORD, 48 | sql_dialect=IBTEST_SQL_DIALECT, 49 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 50 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 51 | ) 52 | c = self.con.cursor() 53 | c.execute("CREATE TABLE T (PK Integer, C1 Integer)") 54 | c.execute("""CREATE TRIGGER EVENTS_AU FOR T ACTIVE 55 | BEFORE UPDATE POSITION 0 56 | AS 57 | BEGIN 58 | if (old.C1 <> new.C1) then 59 | post_event 'c1_updated' ; 60 | END""") 61 | c.execute("""CREATE TRIGGER EVENTS_AI FOR T ACTIVE 62 | AFTER INSERT POSITION 0 63 | AS 64 | BEGIN 65 | if (new.c1 = 1) then 66 | post_event 'insert_1' ; 67 | else if (new.c1 = 2) then 68 | post_event 'insert_2' ; 69 | else if (new.c1 = 3) then 70 | post_event 'insert_3' ; 71 | else 72 | post_event 'insert_other' ; 73 | END""") 74 | self.con.commit() 75 | 76 | def tearDown(self): 77 | self.con.drop_database() 78 | self.con.close() 79 | 80 | def send_events(self, command_list): 81 | c = self.con.cursor() 82 | for cmd in command_list: 83 | c.execute(cmd) 84 | self.con.commit() 85 | 86 | @skip("issue #53: test_events.py freezes on ibcore.py:1829 queue.get()") 87 | def test_one_event(self): 88 | timed_event = threading.Timer(3.0, self.send_events, args=[["insert into T (PK,C1) values (1,1)", ]]) 89 | with self.con.event_conduit(['insert_1']) as events: 90 | timed_event.start() 91 | e = events.wait() 92 | timed_event.join() 93 | self.assertDictEqual(e, {'insert_1': 1}) 94 | 95 | @skip("issue #53: test_events.py freezes on ibcore.py:1829 queue.get()") 96 | def test_multiple_events(self): 97 | cmds = [ 98 | "insert into T (PK,C1) values (1,1)", 99 | "insert into T (PK,C1) values (1,2)", 100 | "insert into T (PK,C1) values (1,3)", 101 | "insert into T (PK,C1) values (1,1)", 102 | "insert into T (PK,C1) values (1,2)", 103 | ] 104 | timed_event = threading.Timer(3.0, self.send_events, args=[cmds]) 105 | with self.con.event_conduit(['insert_1', 'insert_3']) as events: 106 | timed_event.start() 107 | e = events.wait() 108 | timed_event.join() 109 | self.assertDictEqual(e, {'insert_3': 1, 'insert_1': 2}) 110 | 111 | def test_14_events(self): 112 | cmds = [ 113 | "insert into T (PK,C1) values (1,1)", 114 | "insert into T (PK,C1) values (1,2)", 115 | "insert into T (PK,C1) values (1,3)", 116 | "insert into T (PK,C1) values (1,1)", 117 | "insert into T (PK,C1) values (1,2)", 118 | ] 119 | self.e = {} 120 | timed_event = threading.Timer(1.0, self.send_events, args=[cmds]) 121 | with self.con.event_conduit( 122 | [ 123 | 'insert_1', 'A', 'B', 'C', 'D', 124 | 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 125 | 'insert_3' 126 | ] 127 | ) as events: 128 | timed_event.start() 129 | time.sleep(3) 130 | e = events.wait() 131 | timed_event.join() 132 | self.assertDictEqual( 133 | e, 134 | { 135 | 'A': 0, 'C': 0, 'B': 0, 'E': 0, 'D': 0, 'G': 0, 'insert_1': 2, 136 | 'I': 0, 'H': 0, 'K': 0, 'J': 0, 'L': 0, 'insert_3': 1, 'F': 0 137 | } 138 | ) 139 | 140 | @skip("issue #53: test_events.py freezes on ibcore.py:1829 queue.get()") 141 | def test_flush_events(self): 142 | timed_event = threading.Timer(3.0, self.send_events, args=[["insert into T (PK,C1) values (1,1)"]]) 143 | with self.con.event_conduit(['insert_1']) as events: 144 | self.send_events(["insert into T (PK,C1) values (1,1)", "insert into T (PK,C1) values (1,1)"]) 145 | time.sleep(2) 146 | events.flush() 147 | timed_event.start() 148 | e = events.wait() 149 | timed_event.join() 150 | self.assertDictEqual(e, {'insert_1': 1}) 151 | -------------------------------------------------------------------------------- /interbase/test/test_prepared_statement.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_prepared_statement.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import interbase 28 | 29 | from .core import InterBaseTestBase 30 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_PATH, IBTEST_SQL_DIALECT,\ 31 | IBTEST_SERVER_PUBLIC_FILE 32 | 33 | 34 | class TestPreparedStatement(InterBaseTestBase): 35 | def setUp(self): 36 | self.con = interbase.connect( 37 | host=IBTEST_HOST, 38 | database=IBTEST_DB_PATH, 39 | user=IBTEST_USER, 40 | password=IBTEST_PASSWORD, 41 | sql_dialect=IBTEST_SQL_DIALECT, 42 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 43 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 44 | ) 45 | 46 | def tearDown(self): 47 | self.con.execute_immediate("delete from t") 48 | self.con.commit() 49 | self.con.close() 50 | 51 | def test_basic(self): 52 | cur = self.con.cursor() 53 | ps = cur.prep('select * from country') 54 | self.assertEqual(ps._in_sqlda.sqln, 10) 55 | self.assertEqual(ps._in_sqlda.sqld, 0) 56 | self.assertEqual(ps._out_sqlda.sqln, 10) 57 | self.assertEqual(ps._out_sqlda.sqld, 2) 58 | self.assertEqual(ps.statement_type, 1) 59 | self.assertEqual(ps.sql, 'select * from country') 60 | 61 | def test_get_plan(self): 62 | cur = self.con.cursor() 63 | ps = cur.prep('select * from job') 64 | self.assertEqual(ps.plan, "PLAN (JOB NATURAL)") 65 | 66 | def test_execution(self): 67 | cur = self.con.cursor() 68 | ps = cur.prep('select * from country') 69 | cur.execute(ps) 70 | row = cur.fetchone() 71 | self.assertTupleEqual(row, ('USA', 'Dollar')) 72 | 73 | def test_wrong_cursor(self): 74 | cur = self.con.cursor() 75 | cur2 = self.con.cursor() 76 | ps = cur.prep('select * from country') 77 | with self.assertRaises(ValueError) as cm: 78 | cur2.execute(ps) 79 | self.assertTupleEqual( 80 | cm.exception.args, 81 | ('PreparedStatement was created by different Cursor.',) 82 | ) 83 | -------------------------------------------------------------------------------- /interbase/test/test_stored_proc.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_stored_proc.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import interbase 28 | 29 | from .core import InterBaseTestBase 30 | from decimal import Decimal 31 | from .constants import IBTEST_USER, IBTEST_HOST, IBTEST_PASSWORD, IBTEST_DB_PATH, IBTEST_SQL_DIALECT,\ 32 | IBTEST_SERVER_PUBLIC_FILE 33 | 34 | 35 | class TestStoredProc(InterBaseTestBase): 36 | def setUp(self): 37 | self.con = interbase.connect( 38 | host=IBTEST_HOST, 39 | database=IBTEST_DB_PATH, 40 | user=IBTEST_USER, 41 | password=IBTEST_PASSWORD, 42 | sql_dialect=IBTEST_SQL_DIALECT, 43 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 44 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 45 | ) 46 | 47 | def tearDown(self): 48 | self.con.close() 49 | 50 | def test_callproc(self): 51 | cur = self.con.cursor() 52 | result = cur.callproc('sub_tot_budget', ['100']) 53 | self.assertListEqual(result, ['100']) 54 | row = cur.fetchone() 55 | self.assertTupleEqual( 56 | row, 57 | ( 58 | Decimal('3800000'), 59 | Decimal('760000'), 60 | Decimal('500000'), 61 | Decimal('1500000') 62 | ) 63 | ) 64 | result = cur.callproc('sub_tot_budget', [100]) 65 | self.assertListEqual(result, [100]) 66 | row = cur.fetchone() 67 | self.assertTupleEqual( 68 | row, 69 | ( 70 | Decimal('3800000'), 71 | Decimal('760000'), 72 | Decimal('500000'), 73 | Decimal('1500000') 74 | ) 75 | ) 76 | -------------------------------------------------------------------------------- /interbase/test/test_stream_blobs.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_stream_blobs.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import os 28 | import interbase 29 | 30 | from io import StringIO 31 | from .core import InterBaseTestBase 32 | from contextlib import closing 33 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_PATH, IBTEST_SQL_DIALECT,\ 34 | IBTEST_SERVER_PUBLIC_FILE 35 | 36 | 37 | class TestStreamBLOBs(InterBaseTestBase): 38 | def setUp(self): 39 | self.con = interbase.connect( 40 | host=IBTEST_HOST, 41 | database=IBTEST_DB_PATH, 42 | user=IBTEST_USER, 43 | password=IBTEST_PASSWORD, 44 | sql_dialect=IBTEST_SQL_DIALECT, 45 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 46 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 47 | ) 48 | 49 | def tearDown(self): 50 | self.con.execute_immediate("delete from t") 51 | self.con.execute_immediate("delete from t2") 52 | self.con.commit() 53 | self.con.close() 54 | 55 | def testBlobBasic(self): 56 | blob = """InterBase supports two types of blobs, stream and segmented. 57 | The database stores segmented blobs in chunks. 58 | Each chunk starts with a two byte length indicator followed by however many bytes of data were passed as a segment. 59 | Stream blobs are stored as a continuous array of data bytes with no length indicators included.""" 60 | cur = self.con.cursor() 61 | cur.execute('insert into T2 (C1,C9) values (?,?)', [4, StringIO(blob)]) 62 | self.con.commit() 63 | p = cur.prep('select C1,C9 from T2 where C1 = 4') 64 | p.set_stream_blob('C9') 65 | cur.execute(p) 66 | row = cur.fetchone() 67 | blob_reader = row[1] 68 | ## Necessary to avoid bad BLOB handle on BlobReader.close in tearDown 69 | ## because BLOB handle is no longer valid after table purge 70 | with closing(p): 71 | self.assertEqual(blob_reader.read(20), 'InterBase supports t') 72 | self.assertEqual(blob_reader.read(20), 'wo types of blobs, s') 73 | self.assertEqual( 74 | blob_reader.read(400), 75 | 'tream and segmented.\nThe database stores segmented blobs in chunks.\n' 76 | 'Each chunk starts with a two byte length indicator followed by however many ' 77 | 'bytes of data were passed as a segment.\n' 78 | 'Stream blobs are stored as a continuous array of data bytes with no length indicators included.' 79 | ) 80 | self.assertEqual(blob_reader.read(20), '') 81 | self.assertEqual(blob_reader.tell(), 319) 82 | blob_reader.seek(20) 83 | self.assertEqual(blob_reader.tell(), 20) 84 | self.assertEqual(blob_reader.read(20), 'wo types of blobs, s') 85 | blob_reader.seek(0) 86 | self.assertEqual(blob_reader.tell(), 0) 87 | self.assertListEqual(blob_reader.readlines(), StringIO(blob).readlines()) 88 | blob_reader.seek(0) 89 | for line in blob_reader: 90 | self.assertIn(line.rstrip('\n'), blob.split('\n')) 91 | blob_reader.seek(0) 92 | self.assertEqual(blob_reader.read(), blob) 93 | blob_reader.seek(-9, os.SEEK_END) 94 | self.assertEqual(blob_reader.read(), 'included.') 95 | blob_reader.seek(-20, os.SEEK_END) 96 | blob_reader.seek(11, os.SEEK_CUR) 97 | self.assertEqual(blob_reader.read(), 'included.') 98 | blob_reader.seek(61) 99 | self.assertEqual( 100 | blob_reader.readline(), 101 | 'The database stores segmented blobs in chunks.\n' 102 | ) 103 | 104 | def testBlobExtended(self): 105 | blob = """InterBase supports two types of blobs, stream and segmented. 106 | The database stores segmented blobs in chunks. 107 | Each chunk starts with a two byte length indicator followed by however many bytes of data were passed as a segment. 108 | Stream blobs are stored as a continuous array of data bytes with no length indicators included.""" 109 | cur = self.con.cursor() 110 | cur.execute('insert into T2 (C1,C9) values (?,?)', [1, StringIO(blob)]) 111 | cur.execute('insert into T2 (C1,C9) values (?,?)', [2, StringIO(blob)]) 112 | self.con.commit() 113 | p = cur.prep('select C1,C9 from T2') 114 | p.set_stream_blob('C9') 115 | cur.execute(p) 116 | # rows = [row for row in cur] 117 | # Necessary to avoid bad BLOB handle on BlobReader.close in tearDown 118 | # because BLOB handle is no longer valid after table purge 119 | with closing(p): 120 | for row in cur: 121 | blob_reader = row[1] 122 | self.assertEqual(blob_reader.read(20), 'InterBase supports t') 123 | self.assertEqual(blob_reader.read(20), 'wo types of blobs, s') 124 | self.assertEqual( 125 | blob_reader.read(400), 126 | 'tream and segmented.\nThe database stores segmented blobs in chunks.\n' 127 | 'Each chunk starts with a two byte length indicator followed by however many ' 128 | 'bytes of data were passed as a segment.\n' 129 | 'Stream blobs are stored as a continuous array of data bytes with no length indicators included.' 130 | ) 131 | self.assertEqual(blob_reader.read(20), '') 132 | self.assertEqual(blob_reader.tell(), 319) 133 | blob_reader.seek(20) 134 | self.assertEqual(blob_reader.tell(), 20) 135 | self.assertEqual(blob_reader.read(20), 'wo types of blobs, s') 136 | blob_reader.seek(0) 137 | self.assertEqual(blob_reader.tell(), 0) 138 | self.assertListEqual(blob_reader.readlines(), 139 | StringIO(blob).readlines()) 140 | blob_reader.seek(0) 141 | for line in blob_reader: 142 | self.assertIn(line.rstrip('\n'), blob.split('\n')) 143 | blob_reader.seek(0) 144 | self.assertEqual(blob_reader.read(), blob) 145 | blob_reader.seek(-9, os.SEEK_END) 146 | self.assertEqual(blob_reader.read(), 'included.') 147 | blob_reader.seek(-20, os.SEEK_END) 148 | blob_reader.seek(11, os.SEEK_CUR) 149 | self.assertEqual(blob_reader.read(), 'included.') 150 | blob_reader.seek(61) 151 | self.assertEqual( 152 | blob_reader.readline(), 153 | 'The database stores segmented blobs in chunks.\n' 154 | ) 155 | -------------------------------------------------------------------------------- /interbase/test/test_transaction.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | # 3 | # PROGRAM/MODULE: interbase 4 | # FILE: test_transaction.py 5 | # DESCRIPTION: Python driver for InterBase 6 | # CREATED: 12.10.2011 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | import interbase 28 | 29 | from .core import InterBaseTestBase 30 | from .constants import IBTEST_HOST, IBTEST_USER, IBTEST_PASSWORD, IBTEST_DB_PATH, IBTEST_SQL_DIALECT,\ 31 | IBTEST_SERVER_PUBLIC_FILE 32 | 33 | 34 | class TestTransaction(InterBaseTestBase): 35 | def setUp(self): 36 | self.connection = interbase.connect( 37 | host=IBTEST_HOST, 38 | database=IBTEST_DB_PATH, 39 | user=IBTEST_USER, 40 | password=IBTEST_PASSWORD, 41 | sql_dialect=IBTEST_SQL_DIALECT, 42 | ssl=IBTEST_SERVER_PUBLIC_FILE is not None, 43 | server_public_file=IBTEST_SERVER_PUBLIC_FILE 44 | ) 45 | 46 | def tearDown(self): 47 | self.connection.execute_immediate("delete from t") 48 | self.connection.commit() 49 | self.connection.close() 50 | 51 | def test_cursor(self): 52 | transaction = self.connection.main_transaction 53 | transaction.begin() 54 | cur = transaction.cursor() 55 | cur.execute("insert into t (c1) values (1)") 56 | transaction.commit() 57 | cur.execute("select * from t") 58 | rows = cur.fetchall() 59 | self.assertListEqual(rows, [(1,)]) 60 | cur.execute("delete from t") 61 | transaction.commit() 62 | self.assertEqual(len(transaction.cursors), 1) 63 | self.assertIs(transaction.cursors[0], cur) 64 | 65 | def test_context_manager(self): 66 | with interbase.TransactionContext(self.connection) as tr: 67 | cursor = tr.cursor() 68 | cursor.execute("insert into t (c1) values (1)") 69 | 70 | cursor.execute("select * from t") 71 | rows = cursor.fetchall() 72 | self.assertListEqual(rows, [(1,)]) 73 | 74 | try: 75 | with interbase.TransactionContext(self.connection): 76 | cursor.execute("delete from t") 77 | raise Exception() 78 | except Exception as e: 79 | pass 80 | 81 | cursor.execute("select * from t") 82 | rows = cursor.fetchall() 83 | self.assertListEqual(rows, [(1,)]) 84 | 85 | with interbase.TransactionContext(self.connection): 86 | cursor.execute("delete from t") 87 | 88 | cursor.execute("select * from t") 89 | rows = cursor.fetchall() 90 | self.assertListEqual(rows, []) 91 | 92 | def test_savepoint(self): 93 | self.connection.begin() 94 | transaction = self.connection.main_transaction 95 | self.connection.execute_immediate("insert into t (c1) values (1)") 96 | transaction.create_savepoint('test') 97 | self.connection.execute_immediate("insert into t (c1) values (2)") 98 | transaction.rollback(savepoint='test') 99 | transaction.commit() 100 | cursor = transaction.cursor() 101 | cursor.execute("select * from t") 102 | rows = cursor.fetchall() 103 | self.assertListEqual(rows, [(1,)]) 104 | 105 | def test_fetch_after_commit(self): 106 | self.connection.execute_immediate("insert into t (c1) values (1)") 107 | self.connection.commit() 108 | cur = self.connection.cursor() 109 | cur.execute("select * from t") 110 | self.connection.commit() 111 | with self.assertRaises(interbase.DatabaseError) as cm: 112 | rows = cur.fetchall() 113 | self.assertTupleEqual(cm.exception.args, 114 | ('Cannot fetch from this cursor because it has not executed a statement.',)) 115 | 116 | def test_fetch_after_rollback(self): 117 | self.connection.execute_immediate("insert into t (c1) values (1)") 118 | self.connection.rollback() 119 | cur = self.connection.cursor() 120 | cur.execute("select * from t") 121 | self.connection.commit() 122 | with self.assertRaises(interbase.DatabaseError) as cm: 123 | rows = cur.fetchall() 124 | self.assertTupleEqual(cm.exception.args, 125 | ('Cannot fetch from this cursor because it has not executed a statement.',)) 126 | 127 | def test_tpb(self): 128 | tpb = interbase.TPB() 129 | tpb.access_mode = interbase.isc_tpb_write 130 | tpb.isolation_level = interbase.isc_tpb_read_committed 131 | tpb.isolation_level = (interbase.isc_tpb_read_committed, interbase.isc_tpb_rec_version) 132 | tpb.lock_resolution = interbase.isc_tpb_wait 133 | # tpb.lock_timeout = 10 #lock timeouts are not supported since 2017 134 | tpb.table_reservation['COUNTRY'] = (interbase.isc_tpb_protected, interbase.isc_tpb_lock_write) 135 | transaction = self.connection.trans(tpb) 136 | transaction.begin() 137 | transaction.commit() 138 | 139 | def test_transaction_info(self): 140 | self.connection.begin() 141 | transaction = self.connection.main_transaction 142 | info = transaction.transaction_info(interbase.ibase.isc_info_tra_id, 's') 143 | self.assertIn(b'\x04\x04\x00', info) 144 | transaction.commit() 145 | -------------------------------------------------------------------------------- /interbase/utils.py: -------------------------------------------------------------------------------- 1 | #coding:utf-8 2 | # 3 | # PROGRAM: interbase 4 | # MODULE: utils.py 5 | # DESCRIPTION: Various utility classes and functions 6 | # CREATED: 10.5.2013 7 | # 8 | # Software distributed under the License is distributed AS IS, 9 | # WITHOUT WARRANTY OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing rights 11 | # and limitations under the License. 12 | # 13 | # The Original Code was created by Pavel Cisar 14 | # 15 | # Copyright (c) 2011 Pavel Cisar 16 | # and all contributors signed below. 17 | # 18 | # All Rights Reserved. 19 | # Contributor(s): Philippe Makowski 20 | # ______________________________________. 21 | # 22 | # Portions created by Embarcadero Technologies to support 23 | # InterBase are Copyright (c) 2023 by Embarcadero Technologies, Inc. 24 | # 25 | # See LICENSE.TXT for details. 26 | 27 | def update_meta (self, other): 28 | "Helper function for :class:`LateBindingProperty` class." 29 | self.__name__ = other.__name__ 30 | self.__doc__ = other.__doc__ 31 | self.__dict__.update(other.__dict__) 32 | return self 33 | 34 | class LateBindingProperty (property): 35 | """Peroperty class that binds to getter/setter/deleter methods when **instance** 36 | of class that define the property is created. This allows you to override 37 | these methods in descendant classes (if they are not private) without 38 | necessity to redeclare the property itself in descendant class. 39 | 40 | Recipe from Tim Delaney, 2005/03/31 41 | http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/408713 42 | 43 | :: 44 | 45 | class C(object): 46 | 47 | def getx(self): 48 | print 'C.getx' 49 | return self._x 50 | 51 | def setx(self, x): 52 | print 'C.setx' 53 | self._x = x 54 | 55 | def delx(self): 56 | print 'C.delx' 57 | del self._x 58 | 59 | x = LateBindingProperty(getx, setx, delx) 60 | 61 | class D(C): 62 | 63 | def setx(self, x): 64 | print 'D.setx' 65 | super(D, self).setx(x) 66 | 67 | def delx(self): 68 | print 'D.delx' 69 | super(D, self).delx() 70 | 71 | c = C() 72 | c.x = 1 73 | c.x 74 | c.x 75 | del c.x 76 | 77 | print 78 | 79 | d = D() 80 | d.x = 1 81 | d.x 82 | d.x 83 | del d.x 84 | 85 | This has the advantages that: 86 | 87 | a. You get back an actual property object (with attendant memory savings, performance increases, etc); 88 | 89 | b. It's the same syntax as using property(fget, fset, fdel, doc) except for the name; 90 | 91 | c. It will fail earlier (when you define the class as opposed to when you use it). 92 | 93 | d. It's shorter ;) 94 | 95 | e. If you inspect the property you will get back functions with the correct __name__, __doc__, etc. 96 | 97 | """ 98 | def __new__(self, fget=None, fset=None, fdel=None, doc=None): 99 | if fget is not None: 100 | def __get__(obj, objtype=None, name=fget.__name__): 101 | fget = getattr(obj, name) 102 | return fget() 103 | fget = update_meta(__get__, fget) 104 | if fset is not None: 105 | def __set__(obj, value, name=fset.__name__): 106 | fset = getattr(obj, name) 107 | return fset(value) 108 | fset = update_meta(__set__, fset) 109 | if fdel is not None: 110 | def __delete__(obj, name=fdel.__name__): 111 | fdel = getattr(obj, name) 112 | return fdel() 113 | fdel = update_meta(__delete__, fdel) 114 | return property(fget, fset, fdel, doc) 115 | 116 | class Iterator(object): 117 | """Generic iterator implementation. 118 | """ 119 | def __init__(self, method, sentinel = None): 120 | """ 121 | :param method: Callable without parameters that returns next item. 122 | :param sentinel: Value that when returned by `method` indicates the end 123 | of sequence. 124 | """ 125 | self.getnext = method 126 | self.sentinel = sentinel 127 | self.exhausted = False 128 | def __iter__(self): 129 | return self 130 | def next(self): 131 | if self.exhausted: 132 | raise StopIteration 133 | else: 134 | result = self.getnext() 135 | self.exhausted = (result == self.sentinel) 136 | if self.exhausted: 137 | raise StopIteration 138 | else: 139 | return result 140 | __next__ = next 141 | 142 | class EmbeddedProperty(property): 143 | """Property class that forwards calls to getter/setter/deleter methods to 144 | respective property methods of another object. This class allows you to "inject" 145 | properties from embedded object into class definition of parent object.""" 146 | def __init__(self,obj,prop): 147 | """ 148 | :param string obj: Attribute name with embedded object. 149 | :param property prop: Property instance from embedded object. 150 | """ 151 | self.obj = obj 152 | self.prop = prop 153 | self.__doc__ = prop.__doc__ 154 | def __get__(self,obj,objtype): 155 | if obj is None: 156 | return self 157 | return self.prop.__get__(getattr(obj,self.obj)) 158 | def __set__(self,obj,val): 159 | self.prop.__set__(getattr(obj,self.obj),val) 160 | def __delete__(self,obj): 161 | self.prop.__delete__(getattr(obj,self.obj)) 162 | 163 | class EmbeddedAttribute(property): 164 | """Property class that gets/sets attribute of another object. This class 165 | allows you to "inject" attributes from embedded object into class definition 166 | of parent object.""" 167 | def __init__(self,obj,attr): 168 | """ 169 | :param string obj: Attribute name with embedded object. 170 | :param string attr: Attribute name from embedded object. 171 | """ 172 | self.obj = obj 173 | self.attr = attr 174 | self.__doc__ = attr.__doc__ 175 | def __get__(self,obj,objtype): 176 | if obj is None: 177 | return self 178 | return getattr(getattr(obj,self.obj),self.attr) 179 | def __set__(self,obj,val): 180 | setattr(getattr(obj,self.obj),self.attr,val) 181 | 182 | def iter_class_properties(cls): 183 | """Iterator that yields `name, property` pairs for all properties in class. 184 | 185 | :param class cls: Class object.""" 186 | for varname in vars(cls): 187 | value = getattr(cls, varname) 188 | if isinstance(value, property): 189 | yield varname, value 190 | 191 | def iter_class_variables(cls): 192 | """Iterator that yields names of all non-callable attributes in class. 193 | 194 | :param class cls: Class object.""" 195 | for varname in vars(cls): 196 | value = getattr(cls, varname) 197 | if not (isinstance(value, property) or callable(value)): 198 | yield varname 199 | 200 | def embed_attributes(from_class,attr): 201 | """Class decorator that injects properties and non-callable attributes 202 | from another class instance embedded in class instances. 203 | 204 | :param class from_class: Class that should extend decorated class. 205 | :param string attr: Attribute name that holds instance of embedded class 206 | within decorated class instance.""" 207 | def d(class_): 208 | for pname,prop in iter_class_properties(from_class): 209 | if not hasattr(class_,pname): 210 | setattr(class_,pname,EmbeddedProperty(attr,prop)) 211 | for attrname in iter_class_variables(from_class): 212 | if not hasattr(class_,attrname): 213 | setattr(class_,attrname,EmbeddedAttribute(attr,attrname)) 214 | return class_ 215 | return d 216 | 217 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools >= 48", 4 | "setuptools_scm[toml] >= 4, <6", 5 | "setuptools_scm_git_archive", 6 | "wheel >= 0.29.0", 7 | ] 8 | build-backend = 'setuptools.build_meta' 9 | 10 | [tool.setuptools_scm] 11 | version_scheme = "post-release" 12 | local_scheme = "no-local-version" 13 | write_to = "interbase/version.py" 14 | git_describe_command = "git describe --dirty --tags --long --match v* --first-parent" 15 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = 3 | tag_date = 0 4 | tag_svn_revision = 0 5 | 6 | [build_sphinx] 7 | source-dir = sphinx 8 | all-files = True 9 | 10 | 11 | [metadata] 12 | name = interbase 13 | version = 1.5.0 14 | description = InterBase RDBMS bindings for Python. 15 | long_description = file: README.md 16 | long_description_content_type = text/markdown; charset=UTF-8 17 | url = https://github.com/Embarcadero/InterBasePython 18 | author = Sriram Balasubramanian 19 | author_email = sriram.balasubramanian@embarcadero.com 20 | license = BSD 21 | license_files = ['LICENSE.TXT'] 22 | classifiers = 23 | Development Status :: 5 - Production/Stable 24 | License :: OSI Approved :: BSD License 25 | Operating System :: OS Independent 26 | Programming Language :: Python 27 | Topic :: Database 28 | project_urls = 29 | Documentation = https://github.com/Embarcadero/InterBasePython 30 | Source = https://github.com/Embarcadero/InterBasePython 31 | Tracker = https://github.com/Embarcadero/InterBasePython/issues 32 | 33 | [options] 34 | zip_safe = False 35 | packages = find: 36 | platforms = any 37 | include_package_data = True 38 | install_requires = 39 | python_requires = >=3 40 | setup_requires = 41 | setuptools_scm 42 | 43 | [bdist_wheel] 44 | universal = 0 45 | 46 | [aliases] 47 | test=pytest 48 | 49 | [options.extras_require] 50 | test = 51 | pytest >= 6.2.2 52 | all = 53 | %(test)s 54 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import setuptools 3 | 4 | if __name__ == "__main__": 5 | setuptools.setup() 6 | -------------------------------------------------------------------------------- /sphinx/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | 9 | # Internal variables. 10 | PAPEROPT_a4 = -D latex_paper_size=a4 11 | PAPEROPT_letter = -D latex_paper_size=letter 12 | ALLSPHINXOPTS = -d .build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 13 | 14 | .PHONY: help clean html web pickle htmlhelp latex changes linkcheck 15 | 16 | help: 17 | @echo "Please use \`make ' where is one of" 18 | @echo " html to make standalone HTML files" 19 | @echo " pickle to make pickle files" 20 | @echo " json to make JSON files" 21 | @echo " htmlhelp to make HTML files and a HTML help project" 22 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 23 | @echo " changes to make an overview over all changed/added/deprecated items" 24 | @echo " linkcheck to check all external links for integrity" 25 | 26 | clean: 27 | -rm -rf .build/* 28 | 29 | html: 30 | mkdir -p .build/html .build/doctrees 31 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) ../docs 32 | @echo 33 | @echo "Build finished. The HTML pages are in ../docs." 34 | 35 | pickle: 36 | mkdir -p .build/pickle .build/doctrees 37 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) .build/pickle 38 | @echo 39 | @echo "Build finished; now you can process the pickle files." 40 | 41 | web: pickle 42 | 43 | json: 44 | mkdir -p .build/json .build/doctrees 45 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) .build/json 46 | @echo 47 | @echo "Build finished; now you can process the JSON files." 48 | 49 | htmlhelp: 50 | mkdir -p .build/htmlhelp .build/doctrees 51 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) .build/htmlhelp 52 | @echo 53 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 54 | ".hhp project file in .build/htmlhelp." 55 | 56 | latex: 57 | mkdir -p .build/latex .build/doctrees 58 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) .build/latex 59 | @echo 60 | @echo "Build finished; the LaTeX files are in .build/latex." 61 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 62 | "run these through (pdf)latex." 63 | 64 | changes: 65 | mkdir -p .build/changes .build/doctrees 66 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) .build/changes 67 | @echo 68 | @echo "The overview file is in .build/changes." 69 | 70 | linkcheck: 71 | mkdir -p .build/linkcheck .build/doctrees 72 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) .build/linkcheck 73 | @echo 74 | @echo "Link check complete; look for any errors in the above output " \ 75 | "or in .build/linkcheck/output.txt." 76 | -------------------------------------------------------------------------------- /sphinx/changelog.txt: -------------------------------------------------------------------------------- 1 | ######### 2 | Changelog 3 | ######### 4 | 5 | * `Version 1.5.0`_ (15.3.2023) 6 | 7 | Version 1.5.0 8 | ============= 9 | 10 | -------------------------------------------------------------------------------- /sphinx/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Interbase documentation build configuration file, created by 4 | # sphinx-quickstart on Wed Jan 7 12:29:48 2009. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # The contents of this file are pickled, so don't put values in the namespace 9 | # that aren't pickleable (module imports are okay, they're removed automatically). 10 | # 11 | # Note that not all possible configuration values are present in this 12 | # autogenerated file. 13 | # 14 | # All configuration values have a default; values that are commented out 15 | # serve to show the default. 16 | 17 | import sys, os 18 | 19 | # If your extensions are in another directory, add it here. If the directory 20 | # is relative to the documentation root, use os.path.abspath to make it 21 | # absolute, like shown here. 22 | sys.path.append(os.path.abspath('..')) 23 | 24 | # General configuration 25 | # --------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo'] 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | templates_path = ['.templates'] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = '.txt' 36 | 37 | # The encoding of source files. 38 | #source_encoding = 'utf-8' 39 | 40 | # The master toctree document. 41 | master_doc = 'index' 42 | 43 | # General information about the project. 44 | project = u'Interbase' 45 | copyright = u'Embarcadero Technologies, Inc.' 46 | 47 | # The version info for the project you're documenting, acts as replacement for 48 | # |version| and |release|, also used in various other places throughout the 49 | # built documents. 50 | # 51 | # The short X.Y version. 52 | version = '1.5.0' 53 | # The full version, including alpha/beta/rc tags. 54 | release = '1.4.9' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | #language = None 59 | 60 | # There are two options for replacing |today|: either, you set today to some 61 | # non-false value, then it is used: 62 | #today = '' 63 | # Else, today_fmt is used as the format for a strftime call. 64 | #today_fmt = '%B %d, %Y' 65 | 66 | # List of documents that shouldn't be included in the build. 67 | unused_docs = ['usage'] 68 | 69 | # List of directories, relative to source directory, that shouldn't be searched 70 | # for source files. 71 | exclude_trees = ['.build','requirements.txt'] 72 | 73 | exclude_patterns = ['requirements.txt'] 74 | 75 | # The reST default role (used for this markup: `text`) to use for all documents. 76 | #default_role = None 77 | 78 | # If true, '()' will be appended to :func: etc. cross-reference text. 79 | #add_function_parentheses = True 80 | 81 | # If true, the current module name will be prepended to all description 82 | # unit titles (such as .. function::). 83 | #add_module_names = True 84 | 85 | # If true, sectionauthor and moduleauthor directives will be shown in the 86 | # output. They are ignored by default. 87 | #show_authors = False 88 | 89 | # The name of the Pygments (syntax highlighting) style to use. 90 | pygments_style = 'sphinx' 91 | 92 | # Autodoc options 93 | # --------------- 94 | autoclass_content = 'both' 95 | 96 | # Intersphinx options 97 | intersphinx_mapping = {'python': ('http://docs.python.org/', None)} 98 | 99 | # Options for HTML output 100 | # ----------------------- 101 | 102 | html_theme = "interbasetheme" 103 | html_theme_path = ["."] 104 | 105 | # The style sheet to use for HTML and HTML Help pages. A file of that name 106 | # must exist either in Sphinx' static/ path, or in one of the custom paths 107 | # given in html_static_path. 108 | #html_style = 'pyramid.css' 109 | 110 | # The name for this set of Sphinx documents. If None, it defaults to 111 | # " v documentation". 112 | #html_title = None 113 | 114 | # A shorter title for the navigation bar. Default is the same as html_title. 115 | #html_short_title = None 116 | 117 | # The name of an image file (relative to this directory) to place at the top 118 | # of the sidebar. 119 | #html_logo = None 120 | 121 | # The name of an image file (within the static path) to use as favicon of the 122 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 123 | # pixels large. 124 | #html_favicon = None 125 | 126 | # Add any paths that contain custom static files (such as style sheets) here, 127 | # relative to this directory. They are copied after the builtin static files, 128 | # so a file named "default.css" will overwrite the builtin "default.css". 129 | html_static_path = ['interbasetheme/static'] 130 | 131 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 132 | # using the given strftime format. 133 | #html_last_updated_fmt = '%b %d, %Y' 134 | 135 | # If true, SmartyPants will be used to convert quotes and dashes to 136 | # typographically correct entities. 137 | #html_use_smartypants = True 138 | 139 | # Custom sidebar templates, maps document names to template names. 140 | #html_sidebars = {} 141 | 142 | # Additional templates that should be rendered to pages, maps page names to 143 | # template names. 144 | #html_additional_pages = {} 145 | 146 | # If false, no module index is generated. 147 | #html_use_modindex = True 148 | 149 | # If false, no index is generated. 150 | #html_use_index = True 151 | 152 | # If true, the index is split into individual pages for each letter. 153 | #html_split_index = False 154 | 155 | # If true, the reST sources are included in the HTML build as _sources/. 156 | #html_copy_source = True 157 | 158 | # If true, an OpenSearch description file will be output, and all pages will 159 | # contain a tag referring to it. The value of this option must be the 160 | # base URL from which the finished HTML is served. 161 | #html_use_opensearch = '' 162 | 163 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 164 | #html_file_suffix = '' 165 | 166 | # Output file base name for HTML help builder. 167 | htmlhelp_basename = 'Interbasedoc' 168 | 169 | 170 | # Options for LaTeX output 171 | # ------------------------ 172 | 173 | # The paper size ('letter' or 'a4'). 174 | #latex_paper_size = 'letter' 175 | 176 | # The font size ('10pt', '11pt' or '12pt'). 177 | #latex_font_size = '10pt' 178 | 179 | # Grouping the document tree into LaTeX files. List of tuples 180 | # (source start file, target name, title, author, document class [howto/manual]). 181 | latex_documents = [ 182 | ('index', 'Interbase.tex', r'Interbase Documentation', 183 | r'Embarcadero', 'manual'), 184 | ] 185 | 186 | # The name of an image file (relative to this directory) to place at the top of 187 | # the title page. 188 | #latex_logo = None 189 | 190 | # For "manual" documents, if this is true, then toplevel headings are parts, 191 | # not chapters. 192 | #latex_use_parts = False 193 | 194 | # Additional stuff for the LaTeX preamble. 195 | #latex_preamble = '' 196 | 197 | # Documents to append as an appendix to all manuals. 198 | #latex_appendices = [] 199 | 200 | # If false, no module index is generated. 201 | #latex_use_modindex = True 202 | -------------------------------------------------------------------------------- /sphinx/index.txt: -------------------------------------------------------------------------------- 1 | .. Interbase documentation master file, created by sphinx-quickstart on Wed Jan 7 12:29:48 2009. 2 | You can adapt this file completely to your liking, but it should at least 3 | contain the root `toctree` directive. 4 | 5 | ##################################### 6 | Welcome to Interbase's documentation! 7 | ##################################### 8 | 9 | Interbase is a `Python `__ library package that 10 | implements `Python Database API 2.0`-compliant support for the relational 11 | database `InterBase® `__. 12 | In addition to the minimal feature set of the standard Python DB API, 13 | Interbase also exposes nearly the entire native client API of the database engine. 14 | 15 | Interbase is free -- covered by a permissive BSD-style `license 16 | `__ that both commercial and noncommercial users should 17 | find agreeable. 18 | 19 | This documentation set is not a tutorial on Python, SQL, or InterBase; 20 | rather, it is a topical presentation of Interbase's feature set, 21 | with example code to demonstrate basic usage patterns. For detailed 22 | information about InterBase features, see the `InterBase documentation 23 | `. 24 | 25 | Documentation Contents: 26 | *********************** 27 | 28 | .. toctree:: 29 | :maxdepth: 2 30 | 31 | getting-started 32 | usage-guide 33 | python-db-api-compliance 34 | reference 35 | 36 | changelog 37 | license 38 | 39 | 40 | Indices and tables 41 | ****************** 42 | 43 | * :ref:`genindex` 44 | * :ref:`modindex` 45 | * :ref:`search` 46 | 47 | -------------------------------------------------------------------------------- /sphinx/interbasetheme/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | 3 | {%- block extrahead %} 4 | 5 | 6 | 9 | {% endblock %} 10 | 11 | {% block header %} 12 | {%- if logo %} 13 |
14 | 19 |
20 | {%- endif %} 21 | {% endblock %} 22 | 23 | {%- block sidebarlogo %}{%- endblock %} 24 | {%- block sidebarsourcelink %}{%- endblock %} 25 | -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/dialog-note.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/dialog-note.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/dialog-seealso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/dialog-seealso.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/dialog-topic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/dialog-topic.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/dialog-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/dialog-warning.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/epub.css: -------------------------------------------------------------------------------- 1 | /* 2 | * default.css_t 3 | * ~~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- default theme. 6 | * 7 | * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: {{ theme_bodyfont }}; 18 | font-size: 100%; 19 | background-color: {{ theme_footerbgcolor }}; 20 | color: #000; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.document { 26 | background-color: {{ theme_sidebarbgcolor }}; 27 | } 28 | 29 | div.documentwrapper { 30 | float: left; 31 | width: 100%; 32 | } 33 | 34 | div.bodywrapper { 35 | margin: 0 0 0 230px; 36 | } 37 | 38 | div.body { 39 | background-color: {{ theme_bgcolor }}; 40 | color: {{ theme_textcolor }}; 41 | padding: 0 20px 30px 20px; 42 | } 43 | 44 | {%- if theme_rightsidebar|tobool %} 45 | div.bodywrapper { 46 | margin: 0 230px 0 0; 47 | } 48 | {%- endif %} 49 | 50 | div.footer { 51 | color: {{ theme_footertextcolor }}; 52 | width: 100%; 53 | padding: 9px 0 9px 0; 54 | text-align: center; 55 | font-size: 75%; 56 | } 57 | 58 | div.footer a { 59 | color: {{ theme_footertextcolor }}; 60 | text-decoration: underline; 61 | } 62 | 63 | div.related { 64 | background-color: {{ theme_relbarbgcolor }}; 65 | line-height: 30px; 66 | color: {{ theme_relbartextcolor }}; 67 | } 68 | 69 | div.related a { 70 | color: {{ theme_relbarlinkcolor }}; 71 | } 72 | 73 | div.sphinxsidebar { 74 | {%- if theme_stickysidebar|tobool %} 75 | top: 30px; 76 | bottom: 0; 77 | margin: 0; 78 | position: fixed; 79 | overflow: auto; 80 | height: auto; 81 | {%- endif %} 82 | {%- if theme_rightsidebar|tobool %} 83 | float: right; 84 | {%- if theme_stickysidebar|tobool %} 85 | right: 0; 86 | {%- endif %} 87 | {%- endif %} 88 | } 89 | 90 | {%- if theme_stickysidebar|tobool %} 91 | /* this is nice, but it it leads to hidden headings when jumping 92 | to an anchor */ 93 | /* 94 | div.related { 95 | position: fixed; 96 | } 97 | 98 | div.documentwrapper { 99 | margin-top: 30px; 100 | } 101 | */ 102 | {%- endif %} 103 | 104 | div.sphinxsidebar h3 { 105 | font-family: {{ theme_headfont }}; 106 | color: {{ theme_sidebartextcolor }}; 107 | font-size: 1.4em; 108 | font-weight: normal; 109 | margin: 0; 110 | padding: 0; 111 | } 112 | 113 | div.sphinxsidebar h3 a { 114 | color: {{ theme_sidebartextcolor }}; 115 | } 116 | 117 | div.sphinxsidebar h4 { 118 | font-family: {{ theme_headfont }}; 119 | color: {{ theme_sidebartextcolor }}; 120 | font-size: 1.3em; 121 | font-weight: normal; 122 | margin: 5px 0 0 0; 123 | padding: 0; 124 | } 125 | 126 | div.sphinxsidebar p { 127 | color: {{ theme_sidebartextcolor }}; 128 | } 129 | 130 | div.sphinxsidebar p.topless { 131 | margin: 5px 10px 10px 10px; 132 | } 133 | 134 | div.sphinxsidebar ul { 135 | margin: 10px; 136 | padding: 0; 137 | color: {{ theme_sidebartextcolor }}; 138 | } 139 | 140 | div.sphinxsidebar a { 141 | color: {{ theme_sidebarlinkcolor }}; 142 | } 143 | 144 | div.sphinxsidebar input { 145 | border: 1px solid {{ theme_sidebarlinkcolor }}; 146 | font-family: sans-serif; 147 | font-size: 1em; 148 | } 149 | 150 | {% if theme_collapsiblesidebar|tobool %} 151 | /* for collapsible sidebar */ 152 | div#sidebarbutton { 153 | background-color: {{ theme_sidebarbtncolor }}; 154 | } 155 | {% endif %} 156 | 157 | /* -- hyperlink styles ------------------------------------------------------ */ 158 | 159 | a { 160 | color: {{ theme_linkcolor }}; 161 | text-decoration: none; 162 | } 163 | 164 | a:visited { 165 | color: {{ theme_visitedlinkcolor }}; 166 | text-decoration: none; 167 | } 168 | 169 | a:hover { 170 | text-decoration: underline; 171 | } 172 | 173 | {% if theme_externalrefs|tobool %} 174 | a.external { 175 | text-decoration: none; 176 | border-bottom: 1px dashed {{ theme_linkcolor }}; 177 | } 178 | 179 | a.external:hover { 180 | text-decoration: none; 181 | border-bottom: none; 182 | } 183 | 184 | a.external:visited { 185 | text-decoration: none; 186 | border-bottom: 1px dashed {{ theme_visitedlinkcolor }}; 187 | } 188 | {% endif %} 189 | 190 | /* -- body styles ----------------------------------------------------------- */ 191 | 192 | div.body h1, 193 | div.body h2, 194 | div.body h3, 195 | div.body h4, 196 | div.body h5, 197 | div.body h6 { 198 | font-family: {{ theme_headfont }}; 199 | background-color: {{ theme_headbgcolor }}; 200 | font-weight: normal; 201 | color: {{ theme_headtextcolor }}; 202 | border-bottom: 1px solid #ccc; 203 | margin: 20px -20px 10px -20px; 204 | padding: 3px 0 3px 10px; 205 | } 206 | 207 | div.body h1 { margin-top: 0; font-size: 200%; } 208 | div.body h2 { font-size: 160%; } 209 | div.body h3 { font-size: 140%; } 210 | div.body h4 { font-size: 120%; } 211 | div.body h5 { font-size: 110%; } 212 | div.body h6 { font-size: 100%; } 213 | 214 | a.headerlink { 215 | color: {{ theme_headlinkcolor }}; 216 | font-size: 0.8em; 217 | padding: 0 4px 0 4px; 218 | text-decoration: none; 219 | } 220 | 221 | a.headerlink:hover { 222 | background-color: {{ theme_headlinkcolor }}; 223 | color: white; 224 | } 225 | 226 | div.body p, div.body dd, div.body li { 227 | text-align: justify; 228 | line-height: 130%; 229 | } 230 | 231 | div.admonition p.admonition-title + p { 232 | display: inline; 233 | } 234 | 235 | div.admonition p { 236 | margin-bottom: 5px; 237 | } 238 | 239 | div.admonition pre { 240 | margin-bottom: 5px; 241 | } 242 | 243 | div.admonition ul, div.admonition ol { 244 | margin-bottom: 5px; 245 | } 246 | 247 | div.note { 248 | background-color: #eee; 249 | border: 1px solid #ccc; 250 | } 251 | 252 | div.seealso { 253 | background-color: #ffc; 254 | border: 1px solid #ff6; 255 | } 256 | 257 | div.topic { 258 | background-color: #eee; 259 | } 260 | 261 | div.warning { 262 | background-color: #ffe4e4; 263 | border: 1px solid #f66; 264 | } 265 | 266 | p.admonition-title { 267 | display: inline; 268 | } 269 | 270 | p.admonition-title:after { 271 | content: ":"; 272 | } 273 | 274 | pre { 275 | padding: 5px; 276 | background-color: {{ theme_codebgcolor }}; 277 | color: {{ theme_codetextcolor }}; 278 | line-height: 120%; 279 | border: 1px solid #ac9; 280 | border-left: none; 281 | border-right: none; 282 | } 283 | 284 | tt { 285 | background-color: #ecf0f3; 286 | padding: 0 1px 0 1px; 287 | font-size: 0.95em; 288 | } 289 | 290 | th { 291 | background-color: #ede; 292 | } 293 | 294 | .warning tt { 295 | background: #efc2c2; 296 | } 297 | 298 | .note tt { 299 | background: #d6d6d6; 300 | } 301 | 302 | .viewcode-back { 303 | font-family: {{ theme_bodyfont }}; 304 | } 305 | 306 | div.viewcode-block:target { 307 | background-color: #f4debf; 308 | border-top: 1px solid #ac9; 309 | border-bottom: 1px solid #ac9; 310 | } 311 | -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/footerbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/footerbg.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/headerbg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/headerbg.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/ie6.css: -------------------------------------------------------------------------------- 1 | * html img, 2 | * html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none", 3 | this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')", 4 | this.src = "_static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''), 5 | this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')", 6 | this.runtimeStyle.backgroundImage = "none")),this.pngSet=true) 7 | );} 8 | -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/interbasetheme.css_t: -------------------------------------------------------------------------------- 1 | /* 2 | * pylons.css_t 3 | * ~~~~~~~~~~~~ 4 | * 5 | * Sphinx stylesheet -- pylons theme. 6 | * 7 | * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. 8 | * :license: BSD, see LICENSE for details. 9 | * 10 | */ 11 | 12 | @import url("basic.css"); 13 | 14 | /* -- page layout ----------------------------------------------------------- */ 15 | 16 | body { 17 | font-family: "Nobile", sans-serif; 18 | font-size: 100%; 19 | background-color: #393939; 20 | color: #ffffff; 21 | margin: 0; 22 | padding: 0; 23 | } 24 | 25 | div.documentwrapper { 26 | float: left; 27 | width: 100%; 28 | } 29 | 30 | div.bodywrapper { 31 | margin: 0 0 0 {{ theme_sidebarwidth }}px; 32 | } 33 | 34 | hr { 35 | border: 1px solid #B1B4B6; 36 | } 37 | 38 | div.document { 39 | background-color: #eee; 40 | } 41 | 42 | div.header { 43 | width:100%; 44 | background: #f4ad32 url(headerbg.png) repeat-x 0 top; 45 | border-bottom: 2px solid #ffffff; 46 | } 47 | 48 | div.logo { 49 | text-align: center; 50 | padding-top: 10px; 51 | } 52 | 53 | div.body { 54 | background-color: #ffffff; 55 | color: #3E4349; 56 | padding: 0 30px 30px 30px; 57 | font-size: 1em; 58 | border: 2px solid #ddd; 59 | border-right-style: none; 60 | overflow: auto; 61 | } 62 | 63 | div.footer { 64 | color: #ffffff; 65 | width: 100%; 66 | padding: 13px 0; 67 | text-align: center; 68 | font-size: 75%; 69 | background: transparent; 70 | clear:both; 71 | } 72 | 73 | div.footer a { 74 | color: #ffffff; 75 | text-decoration: none; 76 | } 77 | 78 | div.footer a:hover { 79 | color: #e88f00; 80 | text-decoration: underline; 81 | } 82 | 83 | div.related { 84 | line-height: 30px; 85 | color: #373839; 86 | font-size: 0.8em; 87 | background-color: #eee; 88 | } 89 | 90 | div.related a { 91 | color: #1b61d6; 92 | } 93 | 94 | div.related ul { 95 | padding-left: {{ theme_sidebarwidth|toint + 10 }}px; 96 | } 97 | 98 | div.sphinxsidebar { 99 | font-size: 0.75em; 100 | line-height: 1.5em; 101 | } 102 | 103 | div.sphinxsidebarwrapper{ 104 | padding: 10px 0; 105 | } 106 | 107 | div.sphinxsidebar h3, 108 | div.sphinxsidebar h4 { 109 | font-family: "Neuton", sans-serif; 110 | color: #373839; 111 | font-size: 1.4em; 112 | font-weight: normal; 113 | margin: 0; 114 | padding: 5px 10px; 115 | border-bottom: 2px solid #ddd; 116 | } 117 | 118 | div.sphinxsidebar h4{ 119 | font-size: 1.3em; 120 | } 121 | 122 | div.sphinxsidebar h3 a { 123 | color: #000000; 124 | } 125 | 126 | 127 | div.sphinxsidebar p { 128 | color: #888; 129 | padding: 5px 20px; 130 | } 131 | 132 | div.sphinxsidebar p.topless { 133 | } 134 | 135 | div.sphinxsidebar ul { 136 | margin: 10px 20px; 137 | padding: 0; 138 | color: #373839; 139 | } 140 | 141 | div.sphinxsidebar a { 142 | color: #444; 143 | } 144 | 145 | div.sphinxsidebar input { 146 | border: 1px solid #ccc; 147 | font-family: sans-serif; 148 | font-size: 1em; 149 | } 150 | 151 | div.sphinxsidebar input[type=text]{ 152 | margin-left: 20px; 153 | } 154 | 155 | /* -- sidebars -------------------------------------------------------------- */ 156 | 157 | div.sidebar { 158 | margin: 0 0 0.5em 1em; 159 | border: 2px solid #c6d880; 160 | background-color: #e6efc2; 161 | width: 40%; 162 | float: right; 163 | border-right-style: none; 164 | border-left-style: none; 165 | padding: 10px 20px; 166 | } 167 | 168 | p.sidebar-title { 169 | font-weight: bold; 170 | } 171 | 172 | /* -- body styles ----------------------------------------------------------- */ 173 | 174 | a, a .pre { 175 | color: #1b61d6; 176 | text-decoration: none; 177 | } 178 | 179 | a:hover, a:hover .pre { 180 | text-decoration: underline; 181 | } 182 | 183 | /* 184 | margin: 20px -20px 10px -20px; 185 | headfont Trebuchet MS 186 | */ 187 | 188 | div.body h1, 189 | div.body h2, 190 | div.body h3, 191 | div.body h4, 192 | div.body h5, 193 | div.body h6 { 194 | font-family: {{ theme_headfont }}; 195 | background-color: {{ theme_headbgcolor }}; 196 | font-weight: normal; 197 | color: {{ theme_headtextcolor }}; 198 | border-bottom: 1px solid #ccc; 199 | margin: 20px -25px 10px -25px; 200 | padding: 3px 0 3px 10px; 201 | } 202 | 203 | div.body h1 { margin-top: 0; font-size: 200%; } 204 | div.body h2 { font-size: 160%; } 205 | div.body h3 { font-size: 140%; } 206 | div.body h4 { font-size: 120%; } 207 | div.body h5 { font-size: 110%; } 208 | div.body h6 { font-size: 100%; } 209 | 210 | /* Pyramid style 211 | 212 | div.body h1, 213 | div.body h2, 214 | div.body h3, 215 | div.body h4, 216 | div.body h5, 217 | div.body h6 { 218 | font-family: "Neuton", sans-serif; 219 | background-color: #ffffff; 220 | font-weight: normal; 221 | color: #373839; 222 | margin: 30px 0px 10px 0px; 223 | padding: 5px 0; 224 | } 225 | 226 | div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; } 227 | div.body h2 { font-size: 150%; background-color: #ffffff; } 228 | div.body h3 { font-size: 120%; background-color: #ffffff; } 229 | div.body h4 { font-size: 110%; background-color: #ffffff; } 230 | div.body h5 { font-size: 100%; background-color: #ffffff; } 231 | div.body h6 { font-size: 100%; background-color: #ffffff; } 232 | */ 233 | 234 | a.headerlink { 235 | color: #1b61d6; 236 | font-size: 0.8em; 237 | padding: 0 4px 0 4px; 238 | text-decoration: none; 239 | } 240 | 241 | a.headerlink:hover { 242 | text-decoration: underline; 243 | } 244 | 245 | div.body p, div.body dd, div.body li { 246 | line-height: 1.5em; 247 | } 248 | 249 | div.admonition p.admonition-title + p { 250 | display: inline; 251 | } 252 | 253 | div.highlight{ 254 | background-color: white; 255 | } 256 | 257 | div.note { 258 | border: 2px solid #7a9eec; 259 | border-right-style: none; 260 | border-left-style: none; 261 | padding: 10px 20px 10px 60px; 262 | background: #e1ecfe url(dialog-note.png) no-repeat 10px 8px; 263 | } 264 | 265 | div.danger { 266 | border: 2px solid #fbc2c4; 267 | border-right-style: none; 268 | border-left-style: none; 269 | padding: 10px 20px 10px 60px; 270 | background: #fbe3e4 url(dialog-note.png) no-repeat 10px 8px; 271 | } 272 | 273 | div.attention { 274 | border: 2px solid #ffd324; 275 | border-right-style: none; 276 | border-left-style: none; 277 | padding: 10px 20px 10px 60px; 278 | background: #fff6bf url(dialog-note.png) no-repeat 10px 8px; 279 | } 280 | 281 | div.caution { 282 | border: 2px solid #ffd324; 283 | border-right-style: none; 284 | border-left-style: none; 285 | padding: 10px 20px 10px 60px; 286 | background: #fff6bf url(dialog-warning.png) no-repeat 10px 8px; 287 | } 288 | 289 | div.important { 290 | background: #fbe3e4 url(dialog-seealso.png) no-repeat 10px 8px; 291 | border: 2px solid #fbc2c4; 292 | border-left-style: none; 293 | border-right-style: none; 294 | padding: 10px 20px 10px 60px; 295 | } 296 | 297 | div.seealso { 298 | background: #fff6bf url(dialog-seealso.png) no-repeat 10px 8px; 299 | border: 2px solid #ffd324; 300 | border-left-style: none; 301 | border-right-style: none; 302 | padding: 10px 20px 10px 60px; 303 | } 304 | 305 | div.hint, div.tip { 306 | background: #eeffcc url(dialog-topic.png) no-repeat 10px 8px; 307 | border: 2px solid #aacc99; 308 | border-left-style: none; 309 | border-right-style: none; 310 | padding: 10px 20px 10px 60px; 311 | } 312 | 313 | div.topic { 314 | background: #eeeeee; 315 | border: 2px solid #C6C9CB; 316 | padding: 10px 20px; 317 | border-right-style: none; 318 | border-left-style: none; 319 | } 320 | 321 | div.warning, div.error { 322 | background: #fbe3e4 url(dialog-warning.png) no-repeat 10px 8px; 323 | border: 2px solid #fbc2c4; 324 | border-right-style: none; 325 | border-left-style: none; 326 | padding: 10px 20px 10px 60px; 327 | } 328 | 329 | p.admonition-title { 330 | display: none; 331 | } 332 | 333 | p.admonition-title:after { 334 | content: ":"; 335 | } 336 | 337 | pre { 338 | padding: 10px; 339 | background-color: #fafafa; 340 | /* background-color: #eeffcc; */ 341 | color: #222; 342 | line-height: 1.2em; 343 | border: 2px solid #C6C9CB; 344 | /* border: 2px solid #aacc99; */ 345 | font-size: 1.1em; 346 | margin: 1.5em 0 1.5em 0; 347 | border-right-style: none; 348 | border-left-style: none; 349 | } 350 | 351 | tt { 352 | background-color: transparent; 353 | color: #222; 354 | font-size: 1.1em; 355 | font-family: monospace; 356 | } 357 | 358 | .viewcode-back { 359 | font-family: "Nobile", sans-serif; 360 | } 361 | 362 | div.viewcode-block:target { 363 | background-color: #fff6bf; 364 | border: 2px solid #ffd324; 365 | border-left-style: none; 366 | border-right-style: none; 367 | padding: 10px 20px; 368 | } 369 | 370 | table.highlighttable { 371 | width: 100%; 372 | } 373 | 374 | table.highlighttable td { 375 | padding: 0; 376 | } 377 | 378 | a em.std-term { 379 | color: #007f00; 380 | } 381 | 382 | a:hover em.std-term { 383 | text-decoration: underline; 384 | } 385 | 386 | .download { 387 | font-family: "Nobile", sans-serif; 388 | font-weight: normal; 389 | font-style: normal; 390 | } 391 | 392 | tt.xref { 393 | font-weight: normal; 394 | font-style: normal; 395 | } 396 | -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/middlebg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/middlebg.png -------------------------------------------------------------------------------- /sphinx/interbasetheme/static/transparent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Embarcadero/InterBasePython/f2dcefccd1a3fcf0f06d72849a615aba4214106c/sphinx/interbasetheme/static/transparent.gif -------------------------------------------------------------------------------- /sphinx/interbasetheme/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = interbasetheme.css 4 | pygments_style = sphinx.pygment_styles.PyramidStyle 5 | 6 | [options] 7 | rightsidebar = false 8 | stickysidebar = false 9 | collapsiblesidebar = false 10 | externalrefs = false 11 | 12 | footerbgcolor = #11303d 13 | footertextcolor = #ffffff 14 | sidebarbgcolor = #1c4e63 15 | sidebarbtncolor = #3c6e83 16 | sidebartextcolor = #ffffff 17 | sidebarlinkcolor = #98dbcc 18 | relbarbgcolor = #133f52 19 | relbartextcolor = #ffffff 20 | relbarlinkcolor = #ffffff 21 | bgcolor = #ffffff 22 | textcolor = #000000 23 | headbgcolor = white 24 | headtextcolor = #20435c 25 | headlinkcolor = #c60f0f 26 | linkcolor = #355f7c 27 | visitedlinkcolor = #355f7c 28 | codebgcolor = #eeffcc 29 | codetextcolor = #333333 30 | 31 | bodyfont = sans-serif 32 | headfont = 'Neuton', sans-serif 33 | -------------------------------------------------------------------------------- /sphinx/license.txt: -------------------------------------------------------------------------------- 1 | .. include:: ../LICENSE.TXT 2 | 3 | -------------------------------------------------------------------------------- /sphinx/requirements.txt: -------------------------------------------------------------------------------- 1 | interbase --------------------------------------------------------------------------------