initial commit

This commit is contained in:
2025-05-20 09:24:29 -04:00
commit 366d7865ba
142 changed files with 25396 additions and 0 deletions
+89
View File
@@ -0,0 +1,89 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pyrseas.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pyrseas.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
+30
View File
@@ -0,0 +1,30 @@
Augmenter Databases
===================
.. module:: pyrseas.augmentdb
The :mod:`augmentdb` module defines the class :class:`AugmentDatabase`.
Augmenter Database
------------------
An :class:`AugmentDatabase` is derived from
:class:`~pyrseas.database.Database`. It contains two "dictionary"
objects.
One is the :class:`Dicts` container from its parent class. The `db`
Dicts object, defines the database schemas, including their tables and
other objects, by querying the system catalogs.
The second container is an :class:`AugDicts` object. The `adb`
AugDicts object specifies the schemas to be augmented and the
augmenter configuration objects. The latter objects may be supplied
either by other Augmenter modules or from the ``augmenter``
configuration tree on the `aug_map` supplied to the :meth:`apply`
method.
.. autoclass:: AugmentDatabase
.. automethod:: AugmentDatabase.apply
.. automethod:: AugmentDatabase.from_augmap
+42
View File
@@ -0,0 +1,42 @@
Augmentation Objects
====================
These objects are defined in the `aug_map` argument to the `apply`
method of :class:`~pyrseas.augmentdb.AugmentDatabase`. They tie the
desired augmentations, e.g., audit columns, to the tables to be
affected, and the schemas owning the tables.
.. module:: pyrseas.augment.schema
Augmentation Schema
-------------------
.. autoclass:: AugSchema
.. automethod:: AugSchema.apply
.. autoclass:: AugSchemaDict
.. automethod:: AugSchemaDict.from_map
.. automethod:: AugSchemaDict.link_current
.. automethod:: AugSchemaDict.link_refs
.. module:: pyrseas.augment.table
Augmentation Table
------------------
.. autoclass:: AugDbClass
.. autoclass:: AugTable
.. automethod:: AugTable.apply
.. autoclass:: AugClassDict
.. automethod:: AugClassDict.from_map
.. automethod:: AugClassDict.link_current
+39
View File
@@ -0,0 +1,39 @@
Casts
=====
.. module:: pyrseas.dbobject.cast
The :mod:`cast` module defines two classes, :class:`Cast` and
:class:`CastDict`, derived from :class:`DbObject` and
:class:`DbObjectDict`, respectively.
Cast
----
:class:`Cast` is derived from :class:`~pyrseas.dbobject.DbObject` and
represents a `Postgres cast
<https://www.postgresql.org/docs/current/static/sql-createcast.html>`_.
A cast is identified externally as ``cast (<source_type> AS
<target_type>)``.
.. autoclass:: Cast
.. automethod:: Cast.extern_key
.. automethod:: Cast.identifier
.. automethod:: Cast.to_map
.. automethod:: Cast.create
Cast Dictionary
---------------
:class:`CastDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of casts in a database.
.. autoclass:: CastDict
.. automethod:: CastDict.from_map
+97
View File
@@ -0,0 +1,97 @@
Augmenter Configuration Objects
===============================
These configuration objects are predefined in the Augmenter modules or
can be defined or overridden by configuration elements in the
``augmenter`` map. Please see also :doc:`configitems` and
:doc:`predefaug`.
.. module:: pyrseas.augment.function
Configuration Functions
-----------------------
A :class:`CfgFunction` class specifies a Postgres function to be used
by other augmenter objects. For example, this includes procedures to
be invoked by triggers used to maintain audit columns. The
:class:`CfgFunctionDict` class holds all the :class:`CfgFunction`
objects, indexed by the function name and its arguments. A
:class:`CfgFunctionSource` class represents the source code for a
function or part of that source code. A :class:`CfgFunctionTemplate`
class represents the source code for a function, which may include
other elements that can be substituted in the final result. The class
:class:`CfgFunctionSourceDict` holds all the templates currently
defined.
.. autoclass:: CfgFunction
.. automethod:: CfgFunction.apply
.. autoclass:: CfgFunctionDict
.. automethod:: CfgFunctionDict.from_map
.. autoclass:: CfgFunctionSource
.. autoclass:: CfgFunctionTemplate
.. autoclass:: CfgFunctionSourceDict
.. module:: pyrseas.augment.column
Configuration Columns
---------------------
A :class:`CfgColumn` class defines a column to be added to a table by
other augmenter objects. For example, this includes various columns
that serve to capture audit trail information. The columns can be
combined in various ways by the :class:`CfgAuditColumn` objects. The
:class:`CfgColumnDict` class holds all the :class:`CfgColumn` objects,
indexed by column name.
.. autoclass:: CfgColumn
.. automethod:: CfgColumn.apply
.. autoclass:: CfgColumnDict
.. automethod:: CfgColumnDict.from_map
.. module:: pyrseas.augment.trigger
Configuration Triggers
----------------------
A :class:`CfgTrigger` class defines a trigger to be added to a table
by other augmentation objects. For example, this includes triggers to
maintain audit trail columns. The :class:`CfgTriggerDict` class holds
all the :class:`CfgTrigger` objects, indexed by trigger name.
.. autoclass:: CfgTrigger
.. automethod:: CfgTrigger.apply
.. autoclass:: CfgTriggerDict
.. automethod:: CfgTriggerDict.from_map
.. module:: pyrseas.augment.audit
Configuration Audit Columns
---------------------------
A :class:`CfgAuditColumn` class defines a set of attributes (columns,
triggers) to be added to a table. The :class:`CfgAuditColumnDict`
class holds all the :class:`CfgAuditColumn` objects, indexed by
augmentation name.
.. autoclass:: CfgAuditColumn
.. automethod:: CfgAuditColumn.apply
.. autoclass:: CfgAuditColumnDict
.. automethod:: CfgAuditColumnDict.from_map
+91
View File
@@ -0,0 +1,91 @@
Common Command Line Options
===========================
The Pyrseas utilities support the following command line options:
.. cmdoption:: -c <config-file>
--config <config-file>
Specifies an additional `configuration file` to be read and merged
with configuration information from other sources. See
:doc:`config` for more details.
.. cmdoption:: -H <host>
--host <host>
Specifies the `host name` of the machine on which the Postgres
server is running. The default host name is determined by
Postgres (normally, a Unix-domain socket or ``localhost``).
.. cmdoption:: -h, --help
Show help about the program's command line arguments, and exit.
.. cmdoption:: -o <file>
--output <file>
Send output to the specified `file`. If this is omitted, the
standard output is used.
.. cmdoption:: -p <port>
--port <port>
Specifies the `port` on which the Postgres server is listening
for connections. The default port number is determined by
Postgres (normally, 5432).
.. cmdoption:: -r <path>
--repository <path>
Specifies the `path` to a directory where metadata and static data
files will be written to or read from, or where an additional
configuration file can be found. Normally, this will be the root
of a version control repository. If this is not specified on the
command line or in a configuration file, it defaults to the
current working directory.
.. cmdoption:: -U <username>
--user <username>
Postgres `user name` to connect as. The default user name is
determined by Postgres (normally, the name of the operating system
user running the program).
.. cmdoption:: --version
Print the program name and version identifier and exit.
.. cmdoption:: -W, --password
Force the program to prompt for a password before connecting to a
database. If this option is not specified and password
authentication is required, the program will resort to libpq
defaults, i.e., `password file
<https://www.postgresql.org/docs/current/static/libpq-pgpass.html>`_
or `PGPASSWORD environment variable
<https://www.postgresql.org/docs/current/static/libpq-envars.html>`_.
Short options (those only one character long) can be concatenated with
their value arguments, e.g.::
dbtoyaml -p5433 dbname
Several short options can be joined together, using only a single -
prefix, as long as only the last option (or none of them) requires a
value.
Long options (those with names longer than a single-character) can be
separated from their arguments by a '=' or passed as two separate
arguments. For example::
dbtoyaml --port=5433 dbname
or::
dbtoyaml --port 5433 dbname
Long options can be abbreviated as long as the abbreviation is
unambiguous::
dbtoyaml --pass dbname
+31
View File
@@ -0,0 +1,31 @@
Collations
==========
.. module:: pyrseas.dbobject.collation
The :mod:`collation` module defines two classes, :class:`Collation`
and :class:`CollationDict`, derived from :class:`DbSchemaObject` and
:class:`DbObjectDict`, respectively.
Collation
---------
:class:`Collation` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a `Postgres
collation
<https://www.postgresql.org/docs/current/static/collation.html>`_.
.. autoclass:: Collation
.. automethod:: Collation.create
Collation Dictionary
--------------------
:class:`CollationDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of collations in a database.
.. autoclass:: CollationDict
.. automethod:: CollationDict.from_map
+52
View File
@@ -0,0 +1,52 @@
Columns
=======
.. module:: pyrseas.dbobject.column
The :mod:`column` module defines two classes, :class:`Column` derived
from :class:`DbSchemaObject` and :class:`ColumnDict`, derived from
:class:`DbObjectDict`.
Column
------
:class:`Column` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a column of a
table, or an attribute of a composite type. Its :attr:`keylist`
attributes are the schema name and the table name.
A :class:`Column` has the following attributes: :attr:`name`,
:attr:`type`, :attr:`not_null`, :attr:`default` and
:attr:`collation`. The :attr:`number` attribute is also present but is
not made visible externally.
.. autoclass:: Column
.. automethod:: Column.to_map
.. automethod:: Column.add
.. automethod:: Column.add_privs
.. automethod:: Column.diff_privileges
.. automethod:: Column.comment
.. automethod:: Column.drop
.. automethod:: Column.rename
.. automethod:: Column.alter
Column Dictionary
-----------------
Class :class:`ColumnDict` is a dictionary derived from
:class:`~pyrseas.dbobject.DbObjectDict` and represents the collection
of columns in a database, across multiple tables. It is indexed by the
schema name and table name, and each value is a list of
:class:`Column` objects.
.. autoclass:: ColumnDict
.. automethod:: ColumnDict.from_map
+197
View File
@@ -0,0 +1,197 @@
# -*- coding: utf-8 -*-
#
# Pyrseas documentation build configuration file, created by
# sphinx-quickstart on Fri Dec 17 22:06:15 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('..'))
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = "Pyrseas"
copyright = "2010-2022, Joe Abbate"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
import re
from pyrseas import __version__ as release
version = re.match(r'\d+\.\d+(?:\.\d+)?', release).group()
# The full version, including alpha/beta/rc tags.
if 'dev' in release:
release = release[:release.find('dev') + 3]
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'Pyrseasdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Pyrseas.tex', u'Pyrseas Documentation',
u'Joe Abbate', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True
+88
View File
@@ -0,0 +1,88 @@
Configuration
=============
The Pyrseas utilities allow you to configure various options through a
number of YAML specification files, none of which are required--but
the system configuration file is provided by the normal installation.
If a configuration parameter is specified in more than one file, the
latter file in the list of files below overrides any earlier
specification. Any configuration item specified on the command line
takes precedence over any such item in a configuration file.
Configuration File Name
-----------------------
The default configuration file name is ``config.yaml``. If desired,
you can override this with the environment variable
``PYRSEAS_CONFIG_FILE``, but be aware that this will affect all three
levels below.
System Configuration
--------------------
The system configuration file is distributed with Pyrseas and is
normally installed in the ``pyrseas`` library directory.
If desired, you can override this using the ``PYRSEAS_SYS_CONFIG``
environment variable. This can be defined as a full path, including a
file name, or a directory location, in which case the default file
name as mentioned above under `Configuration File Name`_ will be
appended to the path.
Currently, this file includes specifications for functions, triggers
and other objects used by the :program:`dbaugment` utility. It also
includes the default directory path for storing multiple YAML files in
a VCS repository, and the path to data files for use by the data
import and export facilities.
User Configuration
------------------
Each user can have his or her own configuration file. The default
location for this depends on the platform. Under Linux, BSD, OS/X and
other Unix variants, place the file under your home directory, in the
subdirectory ``.config/pyrseas/``. Under Windows, put the file in
``%APPDATA%\pyrseas\``.
You can override the location of the user configuration file using the
``PYRSEAS_USER_CONFIG`` environment variable. This can be defined as
a full path, including a file name, or a directory location, in which
case the default file name as mentioned above under `Configuration
File Name`_ will be appended to the path.
If present, the user configuration file will be merged with the system
configuration.
It is recommended that the user configuration file only be used for
non-project-specific purposes. For example, if you frequently use
Pyrseas against a remote database or on a non-standard port, you can
specify the host or port in your personal configuration file.
Repository Configuration
------------------------
A configuration file can be placed in a version control repository or
project directory, so that it can be under version control together
with other Pyrseas files such as the output from ``dbtoyaml
--multiple-files``. The default location for the repository can be
specified in the user configuration, using the keys ``repository`` and
``path``, for example::
repository:
path: /home/user/project/repo
You can also use the :option:`--repository` command line option to
specify (or override) the directory path to the root of the repository
and the utilities will look for a configuration file in that location.
If present, the repository configuration file will be merged with the
system and user configuration information.
Command Line Configuration
--------------------------
The utilities also allow you to specify a fourth configuration file on
the command line, using the :option:`--config` command line option.
Again, if the file exists, its information will be merged with
previously read files.
+175
View File
@@ -0,0 +1,175 @@
Configuration Items
===================
The following lists the various sections allowed in a configuration
file and the items that are recognized by the Pyrseas utilities.
Augmenter
---------
This section is used by the :program:`dbaugment` utility (see
:doc:`dbaugment`). Most of these are specified in the system
configuration file delivered with Pyrseas, but can also be included or
overridden in user or repository configuration files.
- audit_columns: This section defines combinations of columns and
triggers to be added to tables. Both columns and triggers are
specified as YAML lists (to be consistent with :program:`dbtoyaml`
YAML output), although normally a single trigger will be necessary
per column combination. The columns and triggers should reference
previously defined items in the ``columns`` and ``triggers``
sections (see below). See :doc:`predefaug` for audit columns
defined in the system ``config.yaml``.
- columns: This section defines prototype columns to be added to a
table by Augmenter. For each column, a valid `Postgres data type
<https://www.postgresql.org/docs/current/static/datatype.html>`_
should be included.
You can also add a ``not_null`` constraint and a ``default``
specification. See :doc:`predefaug` for columns defined in the
system ``config.yaml``. In a repository or user configuration file,
you can also specify an alternate name for a previously defined
column. For example, if you prefer that the ``modified_timestamp``
columns be named ``last_update``, you can add the following to a
configuration file::
augmenter:
columns:
modified_timestamp:
name: last_update
- function_templates: This section defines the source text for the
trigger functions (see below) using a template language. Any text
enclosed in double braces, e.g., ``{{modified_by_user}}``, will be
replaced, typically by a previously defined column or its alternate
name (see above).
- functions: This section defines prototype trigger functions to be
invoked by audit columns or other augmentations. The following
items can be specified for each function:
- description: Text for a `COMMENT
<https://www.postgresql.org/docs/current/static/sql-comment.html>`_
statement on the function.
- language: Procedural language, e.g., ``plpgsql``, in which the
function is written.
- returns: Value should be ``trigger``.
- security_definer: Indicates whether the function is to be executed
with the privileges of the user that created it. This is usually
needed for audit column trigger functions.
- source: This is usually a reference to a function template (see
above) enclosed in double braces, e.g.,
``{{functempl_audit_default}}``. However, in user or repository
configurations, this can also be the actual text of the function.
See :doc:`predefaug` for functions defined in the system
configuration file.
- schema pyrseas: This section currently defines three functions that
may be installed in the ``pyrseas`` schema if the ``full`` audit
columns specifications is added for Augmenter processing.
- schemas and tables: Multiple ``schema schema-name`` sections can be
present, typically in a repository configuration file. Each such
section can include ``table table-name`` items, and under each the
``audit_columns`` specifications to be added to the given table.
For example::
augmenter:
schema public:
table t1:
audit_columns: default
- triggers: This section defines the prototype triggers to be used
with audit columns and other augmentations. The following items can
be specified for each trigger:
- events: This is a list that can include one or more of ``insert``,
``update`` or ``delete`` (the latter is not used for audit columns
but may be used in future augmentations).
- level: This can take the values ``row`` or ``statement`` (usually
the former).
- name: This specifies the name to be given to a trigger. It can be
a template using ``{{table_name}}`` which will then be replaced
with the actual table name on which the trigger will act.
- procedure: This is the invocation name, e.g., ``audit_default()``
of the function to be called when the trigger fires.
- timing: This can take the values ``before`` or ``after`` (usually
the former).
Database
--------
This section is primarily for a user configuration file. If you
frequently connect to a particular host, port or as a given user, that
are *not* the Postgres defaults, adding corresponding entries to your
user configuration file allows you to automatically override the
defaults. If for a given invocation you need to connect to or as a
different host, port or user, you can still override the configuration
using the command line options (see :doc:`cmdargs`):
- host: Name of the host to connect. Please refer to the `Postgres
connection host documentation
<https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-HOST>`_
for details and defaults.
- port: Port number to connect to. See the `Postgres connection port
documentation
<https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-PORT>`_
for more.
- username: Name of the user to connect as. View the `Postgres
connection user documentation
<https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNECT-USER>`_
for more.
Datacopy
--------
This section is normally in a user or repository configuration file.
It is used by :program:`dbtoyaml` and :program:`yamltodb` to determine
which tables should be exported from or imported to the database. It
consists of schema names, using the format `schema schema_name`,
followed by lists of table names. For example::
datacopy:
schema public:
- t1
- t2
schema s1:
- t3
Repository
----------
This section is used by all utilities (but :program:`dbaugment` does
not fully support it). The "repository" is intended to be a version
control, e.g., Git, Mercurial, or Subversion, repository.
- data: Path, relative to the root of the repository, where
:program:`dbtoyaml` and :program:`yamltodb` place or expect the
files containing data exported from or imported to the database. The
tables to be exported or imported are specified in the ``Datacopy``
section. The default value (defined in the system ``config.yaml``)
is **metadata**.
- metadata: Path, relative to the root of the repository, where
:program:`dbtoyaml` and :program:`yamltodb` place or expect the YAML
specification files for the database objects when the
`--multiple-files` option is used. The default value (defined
in the system ``config.yaml``) is **metadata**.
- path: Absolute path to the root of the repository. This should
normally be specified in a user configuration file, or in a file
given with the :option:`--config` option. If not specified, this
defaults to the current working directory from which the utility is
run.
+109
View File
@@ -0,0 +1,109 @@
Constraints
===========
.. module:: pyrseas.dbobject.constraint
The :mod:`constraint` module defines six classes: :class:`Constraint`
derived from :class:`DbSchemaObject`, classes
:class:`CheckConstraint`, :class:`PrimaryKey`, :class:`ForeignKey` and
:class:`UniqueConstraint` derived from :class:`Constraint`, and
:class:`ConstraintDict` derived from :class:`DbObjectDict`.
Constraint
----------
Class :class:`Constraint` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a constraint
on a database table. Its :attr:`keylist` attributes are the schema
name, the table name and the constraint name.
.. autoclass:: Constraint
.. automethod:: Constraint.key_columns
.. automethod:: Constraint.add
.. automethod:: Constraint.drop
.. automethod:: Constraint.comment
Check Constraint
----------------
:class:`CheckConstraint` is derived from :class:`Constraint` and represents
a CHECK constraint.
.. autoclass:: CheckConstraint
.. automethod:: CheckConstraint.to_map
.. automethod:: CheckConstraint.add
.. automethod:: CheckConstraint.drop
.. automethod:: CheckConstraint.alter
Primary Key
-----------
:class:`PrimaryKey` is derived from :class:`Constraint` and represents
a primary key constraint.
.. autoclass:: PrimaryKey
.. automethod:: PrimaryKey.to_map
.. automethod:: PrimaryKey.alter
Foreign Key
-----------
:class:`ForeignKey` is derived from :class:`Constraint` and represents
a foreign key constraint.
The following shows a foreign key segment of a map returned by
:meth:`to_map` and expected as argument by
:meth:`ConstraintDict.from_map` exemplifying various possibilities::
{'t1_fgn_key1':
{
'columns': ['c2', 'c3'],
'on_delete': 'restrict',
'on_update': 'set null',
'references':
{'columns': ['pc2', 'pc1'], 'schema': 's1', 'table': 't2'}
}
}
.. autoclass:: ForeignKey
.. automethod:: ForeignKey.ref_columns
.. automethod:: ForeignKey.to_map
.. automethod:: ForeignKey.add
.. automethod:: ForeignKey.alter
Unique Constraint
-----------------
:class:`UniqueConstraint` is derived from :class:`Constraint` and
represents a UNIQUE, non-primary key constraint.
.. autoclass:: UniqueConstraint
.. automethod:: UniqueConstraint.to_map
.. automethod:: UniqueConstraint.alter
Constraint Dictionary
---------------------
Class :class:`ConstraintDict` is a dictionary derived from
:class:`~pyrseas.dbobject.DbObjectDict` and represents the collection
of constraints in a database.
.. autoclass:: ConstraintDict
.. automethod:: ConstraintDict.from_map
+33
View File
@@ -0,0 +1,33 @@
Conversions
===========
.. module:: pyrseas.dbobject.conversion
The :mod:`conversion` module defines two classes, :class:`Conversion`
and :class:`ConversionDict`, derived from :class:`DbSchemaObject` and
:class:`DbObjectDict`, respectively.
Conversion
----------
:class:`Conversion` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a `Postgres
conversion between character set encodings
<https://www.postgresql.org/docs/current/static/sql-createconversion.html>`_.
.. autoclass:: Conversion
.. automethod:: Conversion.to_map
.. automethod:: Conversion.create
Conversion Dictionary
---------------------
:class:`ConversionDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of conversions in a database.
.. autoclass:: ConversionDict
.. automethod:: ConversionDict.from_map
+90
View File
@@ -0,0 +1,90 @@
Databases
=========
.. module:: pyrseas.database
The :mod:`database` module defines class :class:`Database`.
Database
--------
A :class:`Database` can be viewed as a tree of database objects. The
tree may have one or two main branches. A tree with one main branch
is used by :program:`dbtoyaml` to hold the representation of the
database, as read from the Postgres catalogs. :program:`yamltodb`
uses a second main branch to hold the representation as read from the
YAML input specification.
Each main branch consists of multiple subtrees for different kinds of
objects. For example, the Schemas (Postgres namespaces) subtree has
all the Postgres schema objects, the Procedures subtree has all the
Postgres functions and aggregates. The objects in the subtrees are
connected in implicit or explicit manners to related objects. For
example, the objects in the ``schema public`` are implicitly
accessible from the corresponding :class:`Schema` object because they
all share ``public`` as the first part of their internal key (see
:meth:`DbObject.key`). As another example, a table has explicit
links to constraints and indexes defined on it.
A :class:`Database` is initialized from a
:class:`~pyrseas.database.CatDbConnection` object (a specialized class
derived from :class:`~pyrseas.lib.dbconn.DbConnection`). It consists of
one or two :class:`Dicts` (the main branches in the above
discussion). A :class:`Dicts` object holds various dictionary objects
derived from :class:`~pyrseas.dbobject.DbObjectDict`, e.g.,
:class:`~pyrseas.dbobject.schema.SchemaDict`,
:class:`~pyrseas.dbobject.table.ClassDict`, and
:class:`~pyrseas.dbobject.column.ColumnDict`. The key for each
dictionary is a Python tuple (or a single value in the case of
:class:`SchemaDict` and other non-schema objects). For example, the
:class:`~pyrseas.dbobject.table.ClassDict` dictionary is indexed by
(`schema name`, `table name`)--in this context `table name` may
actually be a `sequence name`, a `view name` or a `materialized view
name`. In addition, object instances in each dictionary are linked to
related objects in other dictionaries, e.g., columns are linked to the
tables where they belong.
The :attr:`db` :class:`Dicts` object --always present-- instantiates
the database schemas, including their tables and other objects, by
querying the system catalogs. The :attr:`ndb` :class:`Dicts` object
instantiates the schemas based on the :obj:`input_map` supplied to the
:meth:`diff_map` method.
The :meth:`to_map` method returns and the :meth:`diff_map` method
takes as input, a Python dictionary (equivalent to a YAML or JSON
object) as shown below. It uses 'schema `schema_name`' as the key for
each schema. The value corresponding to each 'schema `schema_name`' is
another dictionary using 'sequences', 'tables', etc., as keys and more
dictionaries as values. For example::
{'schema public':
{'sequence seq1': { ... },
'sequence seq2': { ... },
'table t1': { ... },
'table t2': { ... },
'table t3': { ... },
'view v1': { ... }
},
'schema s1': { ... },
'schema s2': { ... }
}
Refer to :class:`~pyrseas.dbobject.table.Sequence`,
:class:`~pyrseas.dbobject.table.Table` and
:class:`~pyrseas.dbobject.table.View` for details on the lower level
dictionaries.
.. autoclass:: Database
Methods :meth:`from_catalog` and :meth:`from_map` are for internal
use. Methods :meth:`to_map` and :meth:`diff_map` are the external API.
.. automethod:: Database.from_catalog
.. automethod:: Database.from_map
.. automethod:: Database.map_from_dir
.. automethod:: Database.to_map
.. automethod:: Database.diff_map
+108
View File
@@ -0,0 +1,108 @@
dbaugment - Augment a database
==============================
Name
----
dbaugment -- Augment a Postgres database in predefined ways
Synopsis
--------
::
dbaugment [option...] dbname [spec]
Description
-----------
:program:`dbaugment` is a utility for augmenting a Postgres database
with various standard attributes and procedures, such as automatically
maintained audit columns. The augmentations are defined in a
YAML-formatted ``spec`` file.
The following is an example of a specification file::
augmenter:
columns:
modified_date:
not_null: true
type: date
schema public:
table t1:
audit_columns: default
table t3:
audit_columns: modified_only
The specification file lists each schema, and within it, each table to
be augmented. Under each table the following values are currently
recognized:
- audit_columns: This indicates that audit trail columns are to be
added to the table, e.g., a timestamp column recording when a row
was last modified.
The first section of the specification file, under the ``augmenter``
header, lists configuration information. This is in addition to the
built-in configuration objects (see :ref:`predef-aug`).
:program:`dbaugment` first reads the database catalogs. It also
initializes itself from predefined configuration information.
:program:`dbaugment` then reads the specification file, which may
include additional configuration objects, and outputs a YAML file,
including the existing catalog information together with the desired
enhancements. The YAML file is suitable for input to
:program:`yamltodb` to generate the SQL statements to implement the
changes.
Options
-------
:program:`dbaugment` accepts the following command-line arguments (in
addition to the :doc:`cmdargs`):
**dbname**
Specifies the name of the database whose schema is to augmented.
**spec**
Location of the file with the augmenter specifications. If this
is omitted, the specification is read from the program's standard
input.
Examples
--------
To augment a database called ``moviesdb`` according to the
specifications in the file ``movies.yaml``::
dbaugment moviesdb movies.yaml
To add a column named ``updated`` to table ``public.film`` to hold the
date and time each row was inserted or updated, create a YAML
specification file, say ``film.yaml`` as follows::
augmenter:
columns:
modified_timestamp:
name: updated
schema public:
table film:
audit_columns: modified_only
The first four lines configure the predefined ``modified_timestamp``
audit column to use the name ``updated`` instead. The last three
lines direct ``dbaugment`` to apply the predefined ``modified_only``
audit column to the ``film`` table.
Then run the following command to generate the resulting database
specification, alter the table and create the needed trigger and
function.
dbaugment moviesdb film.yaml | yamltodb moviesdb -u
See Also
--------
:ref:`predef-aug`
+101
View File
@@ -0,0 +1,101 @@
Database Objects
================
.. module:: pyrseas.dbobject
The :mod:`dbobject` module defines two low-level classes and an
intermediate class. Most Pyrseas classes are derived from either
:class:`DbObject` or :class:`DbObjectDict`.
Database Object
---------------
A :class:`DbObject` represents a database object such as a schema,
table, or column, defined in a Postgres `system catalog
<https://www.postgresql.org/docs/current/static/catalogs.html>`_. It is
initialized from a dictionary of attributes. Derived classes should
define a :attr:`keylist` that is a list of attribute names that
uniquely identify each object instance within the database.
.. autoclass:: DbObject
.. autoattribute:: DbObject.objtype
.. autoattribute:: DbObject.keylist
.. automethod:: DbObject.key
The following methods are generally used to map objects for external
output:
.. automethod:: DbObject.extern_key
.. automethod:: DbObject.query
.. automethod:: DbObject.extern_filename
.. automethod:: DbObject.identifier
.. automethod:: DbObject.to_map
.. automethod:: DbObject.map_privs
The following methods generate SQL statements from the object
properties and sometimes from a second object:
.. automethod:: DbObject.comment
.. automethod:: DbObject.alter_owner
.. automethod:: DbObject.drop
.. automethod:: DbObject.rename
.. automethod:: DbObject.alter
.. automethod:: DbObject.diff_privileges
.. automethod:: DbObject.diff_description
Database Object Dictionary
--------------------------
A :class:`DbObjectDict` represents a collection of :class:`DbObject`'s
and is derived from the Python built-in type :class:`dict`. If a
:class:`~pyrseas.lib.dbconn.DbConnection` object is used for
initialization, an internal method is called to initialize the
dictionary from the database catalogs. The :class:`DbObjectDict`
:meth:`fetch` method fetches all objects using the `query` method
defined by derived classes. Derived classes should also define a
:attr:`cls` attribute for the associated :class:`DbObject` class,
e.g., :class:`~pyrseas.schema.SchemaDict` sets :attr:`cls` to
:class:`~pyrseas.schema.Schema`.
.. autoclass:: DbObjectDict
.. autoattribute:: DbObjectDict.cls
.. automethod:: DbObjectDict.to_map
.. automethod:: DbObjectDict.fetch
Schema Object
-------------
A :class:`DbSchemaObject` is derived from :class:`DbObject`. It is
used as a base class for objects owned by a schema and to define
certain common methods. This is different from the
:class:`~pyrseas.schema.Schema` that represents the schema (Postgres
namespace) itself.
.. autoclass:: DbSchemaObject
.. automethod:: DbSchemaObject.identifier
.. automethod:: DbSchemaObject.qualname
.. automethod:: DbSchemaObject.unqualify
.. automethod:: DbSchemaObject.rename
+293
View File
@@ -0,0 +1,293 @@
dbtoyaml - Database to YAML
===========================
Name
----
dbtoyaml -- extract the schema of a Postgres database in YAML format
Synopsis
--------
::
dbtoyaml [option...] dbname
Description
-----------
:program:`dbtoyaml` is a utility for extracting the schema of a
Postgres database to a `YAML <http://yaml.org>`_ formatted
specification. By default, the specification is output as a single
output stream, which can be redirected or explicitly sent to a file.
As an alternative, the ``--multiple-files`` option allows you to break
down the specification into multiple files, in general, one for each
object (see `Multiple File Output`_).
Note that `JSON <http://json.org/>`_ is an official
subset of YAML version 1.2, so the :program:`dbtoyaml` output should
also be compatible with JSON tools.
A sample of the output format is as follows::
schema public:
owner: postgres
privileges:
- postgres:
- all
- PUBLIC:
- all
table t1:
check_constraints:
t1_c2_check:
columns:
- c2
expression: (c2 > 123)
columns:
- c1:
not_null: true
type: integer
- c2:
type: smallint
- c3:
default: 'false'
type: boolean
- c4:
type: text
foreign_keys:
t1_c2_fkey:
columns:
- c2
references:
columns:
- c21
schema: s1
table: t2
owner: alice
primary_key:
t1_pkey:
columns:
- c1
schema s1:
owner: bob
privileges:
- bob:
- all
- alice:
- all
table t2:
columns:
- c21:
not_null: true
type: integer
- c22:
type: character varying(16)
owner: bob
primary_key:
t2_pkey:
columns:
- c21
privileges:
- bob:
- all
- PUBLIC:
- select
- alice:
- insert:
grantable: true
- delete:
grantable: true
- update:
grantable: true
- carol:
grantor: alice
privs:
- insert
The above should be mostly self-explanatory. The example database has
two tables, named ``t1`` and ``t2``, the first --owned by user
'alice'-- in the ``public`` schema and the second --owned by user
'bob'-- in a schema named ``s1`` (also owned by 'bob').
The ``columns:`` specifications directly under each table list each
column in that table, in the same order as shown by Postgres. The
specifications ``primary_key:``, ``foreign_keys:`` and
``check_constraints:`` define PRIMARY KEY, FOREIGN KEY and CHECK
constraints for a given table. Additional specifications (not shown)
define unique constraints and indexes.
User 'bob' has granted all privileges to 'alice' on the ``s1`` schema.
On table ``t2``, he also granted SELECT to PUBLIC; INSERT, UPDATE and
DELETE to 'alice' with GRANT OPTION; and she has in turn granted
INSERT to user 'carol'.
:program:`dbtoyaml` currently supports extracting information about
nearly all types of Postgres database objects. See :ref:`api-ref`
for a list of supported objects.
The behavior and options of ``dbtoyaml`` are patterned after the
`pg_dump utility
<https://www.postgresql.org/docs/current/static/app-pgdump.html>`_
since it is most analogous to using ``pg_dump --schema-only``.
Multiple File Output
--------------------
.. program:: dbtoyaml
The :option:`--multiple-files` option breaks down the output into
multiple files under a given root directory. The root is created if
it does not exist. The root directory name defaults to ``metadata``
in the system configuration file. The location of the root directory
defaults to the configuration item ``repository.path`` or can be
specified using the `--repository` option (see :doc:`config`
and :doc:`cmdargs` for further details).
The first level contains ``schema.<name>`` subdirectories,
``schema.<name>.yaml`` files and ``<objtype>.<name>.yaml`` files,
where ``<name>`` is the name of the corresponding objects and
``<objtype>`` is the type of top-level (non-schema) object. Note that
non-schema refers to Postgres extensions, casts, languages or
foreign data wrappers.
The second level, i.e., the ``schema.<name>`` subdirectories contain
``<objtype>.<name>.yaml`` files for each object in the particular
schema (but see below for caveats).
Object Name Conflicts
~~~~~~~~~~~~~~~~~~~~~
The names of Postgres objects can include characters that are not
allowed in filesystem object names. The most common example is the
division operator ('/'), but even table names can include
non-alphanumeric characters, if the identifiers are quoted.
In addition, one can define two or more objects with the same base
name, e.g., function ``foo(integer)`` and function ``foo(text)``, or a
table named ``"My Table"`` and another named ``"my table"`` or
``"MY TABLE"``. On certain operating systems, i.e., Windows, it is not
possible to create two files in the same directory that differ only in
the case of their characters.
In order to deal with the aforementioned issues, ``dbtoyaml`` places
certain objects in common files and transforms object identifiers so
that they are suitable for use in files and directories. For example,
the information for all user-defined casts are written to the file
``cast.yaml`` in the root directory. Functions with the same name but
different arguments are written to a single file, e.g.,
``function.foo.yaml`` in the first example above. Identifiers are
also converted to all lowercase, non-alphanumeric characters
(excluding underscore) are converted to underscores and, by default,
schema object names are truncated to 32 characters.
If two object names, thus transformed, map to the same string, then
the objects' information is written to the same file, e.g.,
``table.my_table.yaml`` in the second example above. If you prefer to
change the default truncation length, please define the environment
variable ``PYRSEAS_MAX_IDENT_LEN`` to some integer value (up to 63).
Version Control and Dropped Objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It is expected that the output of ``dbtoyaml --multiple-files`` will
be placed under version control. Further invocations should then
update the files in the same directory tree. However, if an object is
dropped from the database ``dbtoyaml`` would normally only output
files for new or changed objects--and thus keep the dropped object
file under version control. To deal with dropped objects, ``dbtoyaml
-m`` outputs a special YAML "index" file, named
``database.<dbname>.yaml`` in the root directory. When ``dbtoyaml
-m`` is run a second time, it looks for this "index" file and if
found, proceeds to delete the previous run's ``.yaml`` files before
outputting new ones.
Options
-------
:program:`dbtoyaml` accepts the following command-line arguments (in
addition to the :doc:`cmdargs`):
dbname
Specifies the name of the database whose schema is to be extracted.
.. cmdoption:: -m, --multiple-files
Extracts the schema to a two-level directory tree. See `Multiple
File Output`_ above.
.. cmdoption:: -n <schema>
--schema <schema>
Extracts only a schema matching `schema`. By default, all schemas
are extracted. Multiple schemas can be extracted by using multiple
``-n`` switches. Note that normally all objects that belong to the
schema are extracted as well, unless excluded otherwise.
.. cmdoption:: -N <schema>
--exclude-schema <schema>
Does not extract schema matching `schema`. This can be given more
than once to exclude several schemas.
.. cmdoption:: -O, --no-owner
Do not output object ownership information. By default, as seen
in the sample output above, database objects (schemas, tables,
etc.) that can be owned by some user, are shown with an "owner:
*username*" element. The :option:`-O` switch suppresses all those
lines.
NOTE: If you specify `--no-owner`, you will most likely also want
to specify :option:`--no-privileges`. If the former is used
without the latter the resulting YAML output will have privilege
information without user data, which will cause errors if the YAML
is then fed to :doc:`yamltodb`.
.. cmdoption:: -t <table>
--table <table>
Extract only tables matching `table`. Multiple tables can be
extracted by using multiple :option:`-t` switches. Note that
selecting a table may cause other objects, such as an owned
sequence, to be extracted as well
.. cmdoption:: -T <table>
--exclude-table <table>
Do not extract tables matching `table`. Multiple tables can be
excluded by using multiple :option:`-T` switches.
.. cmdoption:: -x, --no-privileges
Do not output access privilege information. By default, as seen
in the sample output above, if specific GRANTs have been issued on
various objects (schemas, tables, etc.), the privileges are shown
under each object. The :option:`-x` switch suppresses all those
lines.
See also the NOTE under :option:`--no-owner`.
Examples
--------
To extract a database called ``moviesdb`` into a file::
dbtoyaml moviesdb > moviesdb.yaml
To extract only the schema named ``store``::
dbtoyaml --schema=store moviesdb > moviesdb.yaml
To extract the tables named ``film`` and ``genre``::
dbtoyaml -t film -t genre moviesdb -o moviesdb.yaml
To extract objects, to standard output, except those in schemas
``product`` and ``store``::
dbtoyaml -N product -N store moviesdb
To extract objects to a directory under version control::
dbtoyaml moviesdb -m movies/dbspec
+97
View File
@@ -0,0 +1,97 @@
.. _development:
Development
===========
The following details the tools needed to contribute to the
development of Pyrseas. If you have any doubts or questions, please
open an issue on GitHub (https://github.com/perseas/Pyrseas/issues).
In addition, see *Version Control* below on how to set up a GitHub
account to participate in development.
Requirements
------------
- Git
- Python
- Postgres
- Psycopg3
- PyYAML
- Tox
Version Control
---------------
Pyrseas uses `Git <https://git-scm.com/>`_ to control changes to its
source code. As mentioned under :ref:`download`, the master Git
`repository <https://github.com/perseas/Pyrseas>`_ is located at GitHub.
To install Git, either `download and install
<https://git-scm.com/download>`_ the latest stable release for your
platform or follow the `Pro Git` `installation instructions
<https://git-scm.com/book/en/Getting-Started-Installing-Git>`_. For
most Linux users, ``apt-get`` or ``yum`` (depending on Linux flavor)
will be the simplest means to install the ``git-core`` package. For
Windows, downloading the installer and selecting ``Git Bash`` gives
you not only Git but a Bash shell, which is handy if you're coming
from a Linux/Unix background.
Once Git is installed, change to a suitable directory and clone the
master repository::
git clone https://github.com/perseas/Pyrseas.git
To be able to create a fork on GitHub, open an issue or participate in
Pyrseas development, you'll first have to `create a GitHub account
<https://github.com/join>`_.
Programming Language
--------------------
To contribute to Pyrseas, you need a version of `Python
<https://www.python.org>`_. You can develop using Python 3.7 or higher.
If Python is not already available on your machine, either `download
and install one or both <https://www.python.org/downloads/>`_ of the
production releases for your platform, follow the applicable
installation instructions given in `The Hitchhikers Guide to Python!
<http://docs.python-guide.org/en/latest/>`_ or install it from your
platform's package management system.
Database Installation
---------------------
To participate in Pyrseas development, you'll also need one or more
installations of `Postgres <https://www.postgresql.org>`_, versions
13, 12, 11 or 10. If you only have limited space, it is
preferable to install one of the latest two versions.
The versions can be obtained as binary packages or installers from the
`Postgres.org website <https://www.postgresql.org/download/>`_. The
site also includes instructions for installing from package management
systems or building it from source.
To access Postgres from Python, you have to install the `Psycopg
<https://www.psycopg.org/>`_ version 3 adapter. You can either follow the
instructions in `Psycopg's site
<https://www.psycopg.org/psycopg3/docs/basic/install.html>`_, or install it from
your package management system.
Other Libraries and Tools
-------------------------
The ``dbtoyaml`` and ``yamltodb`` utilities use the `PyYAML
<http://pyyaml.org/wiki/PyYAML>`_ library. You can install it from
the PyYAML site, or possibly from your package management system. For
Windows 64-bit, please read the note under :ref:`installer`.
To easily run the Pyrseas tests against various Python/Postgres
version combinations, you will need `pytest
<https://pytest.readthedocs.io/en/latest/>`_ and `Tox
<https://tox.readthedocs.io/en/latest/>`_. Please refer to
:ref:`testing` for more information.
+33
View File
@@ -0,0 +1,33 @@
Event Triggers
==============
.. module:: pyrseas.dbobject.eventtrig
The :mod:`eventtrig` module defines two classes, :class:`EventTrigger` and
:class:`EventTriggerDict`, derived from :class:`DbObject` and
:class:`DbObjectDict`, respectively.
Event Trigger
--------------
:class:`EventTrigger` is derived from
:class:`~pyrseas.dbobject.DbObject` and represents an `event trigger
<https://www.postgresql.org/docs/current/static/event-triggers.html>`_
available from Postgres 9.3 onwards.
.. autoclass:: EventTrigger
.. automethod:: EventTrigger.to_map
.. automethod:: EventTrigger.create
Event Trigger Dictionary
------------------------
:class:`EventTriggerDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of event triggers in a database.
.. autoclass:: EventTriggerDict
.. automethod:: EventTriggerDict.from_map
+33
View File
@@ -0,0 +1,33 @@
Extensions
==========
.. module:: pyrseas.dbobject.extension
The :mod:`extension` module defines two classes, :class:`Extension`
and :class:`ExtensionDict`, derived from :class:`DbObject` and
:class:`DbObjectDict`, respectively.
Extension
---------
:class:`Extension` is derived from
:class:`~pyrseas.dbobject.DbObject` and represents a `Postgres
extension
<https://www.postgresql.org/docs/current/static/extend-extensions.html>`_.
.. autoclass:: Extension
.. automethod:: Extension.create
.. automethod:: Extension.alter
Extension Dictionary
--------------------
:class:`ExtensionDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of extensions in a database.
.. autoclass:: ExtensionDict
.. automethod:: ExtensionDict.from_map
+142
View File
@@ -0,0 +1,142 @@
Foreign Data Objects
====================
.. module:: pyrseas.dbobject.foreign
The :mod:`foreign` module defines nine classes related to Postgres
foreign data wrappers (FDWs), namely: :class:`DbObjectWithOptions`
derived from :class:`DbObject`, classes :class:`ForeignDataWrapper`,
:class:`ForeignServer` and :class:`UserMapping` derived from
:class:`DbObjectWithOptions`, :class:`ForeignTable` derived from
:class:`DbObjectWithOptions` and :class:`Table`, classes
:class:`ForeignDataWrapperDict`, :class:`ForeignServerDict` and
:class:`UserMappingDict` derived from :class:`DbObjectDict`, and
:class:`ForeignTableDict` derived from :class:`ClassDict`.
Database Object With Options
----------------------------
:class:`DbObjectWithOptions` is derived from
:class:`~pyrseas.dbobject.DbObject`. It is a helper class for dealing
with the OPTIONS clauses common to the foreign data objects.
.. autoclass:: DbObjectWithOptions
.. automethod:: DbObjectWithOptions.to_map
.. automethod:: DbObjectWithOptions.options_clause
.. automethod:: DbObjectWithOptions.diff_options
.. automethod:: DbObjectWithOptions.alter
Foreign Data Wrapper
--------------------
:class:`ForeignDataWrapper` is derived from `DbObjectWithOptions` and
represents a `Postgres foreign data wrapper
<https://www.postgresql.org/docs/current/static/sql-createforeigndatawrapper.html>`_.
See also `Foreign Data
<https://www.postgresql.org/docs/current/static/ddl-foreign-data.html>`_
and `Writing A Foreign Data Wrapper
<https://www.postgresql.org/docs/current/static/fdwhandler.html>`_.
.. autoclass:: ForeignDataWrapper
.. automethod:: ForeignDataWrapper.to_map
.. automethod:: ForeignDataWrapper.create
Foreign Data Wrapper Dictionary
-------------------------------
:class:`ForeignDataWrapperDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of foreign data wrappers in a database.
.. autoclass:: ForeignDataWrapperDict
.. automethod:: ForeignDataWrapperDict.from_map
Foreign Server
--------------
:class:`ForeignServer` is derived from :class:`DbObjectWithOptions`
and represents a `Postgres foreign server
<https://www.postgresql.org/docs/current/static/sql-createserver.html>`_.
.. autoclass:: ForeignServer
.. automethod:: ForeignServer.identifier
.. automethod:: ForeignServer.to_map
.. automethod:: ForeignServer.create
Foreign Server Dictionary
-------------------------
:class:`ForeignServerDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a Python dictionary
that represents the collection of foreign servers in a database.
.. autoclass:: ForeignServerDict
.. automethod:: ForeignServerDict.from_map
.. automethod:: ForeignServerDict.to_map
User Mapping
------------
:class:`UserMapping` is derived from :class:`DbObjectWithOptions` and
represents a `mapping of a Postgres user to a foreign server
<https://www.postgresql.org/docs/current/static/sql-createusermapping.html>`_.
.. autoclass:: UserMapping
.. automethod:: UserMapping.extern_key
.. automethod:: UserMapping.identifier
.. automethod:: UserMapping.create
User Mapping Dictionary
-----------------------
:class:`UserMappingDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of user mappings in a database.
.. autoclass:: UserMappingDict
.. automethod:: UserMappingDict.from_map
.. automethod:: UserMappingDict.to_map
Foreign Table
-------------
:class:`ForeignTable` is derived from :class:`DbObjectWithOptions` and
:class:`~pyrseas.dbobject.table.Table`. It represents a `Postgres
foreign table
<https://www.postgresql.org/docs/current/static/sql-createforeigntable.html>`_.
.. autoclass:: ForeignTable
.. automethod:: ForeignTable.to_map
.. automethod:: ForeignTable.create
.. automethod:: ForeignTable.drop
Foreign Table Dictionary
------------------------
:class:`ForeignTableDict` is derived from
:class:`~pyrseas.dbobject.table.ClassDict`. It is a dictionary that
represents the collection of foreign tables in a database.
.. autoclass:: ForeignTableDict
.. automethod:: ForeignTableDict.from_map
+65
View File
@@ -0,0 +1,65 @@
Functions
=========
.. module:: pyrseas.dbobject.function
The :mod:`function` module defines four classes: class :class:`Proc`
derived from :class:`DbSchemaObject`, classes :class:`Function` and
:class:`Aggregate` derived from :class:`Proc`, and class
:class:`ProcDict` derived from :class:`DbObjectDict`.
Procedure
---------
Class :class:`Proc` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a regular or
aggregate function.
.. autoclass:: Proc
.. automethod:: Proc.extern_key
.. automethod:: Proc.identifier
Function
--------
:class:`Function` is derived from :class:`Proc` and represents a
`Postgres user-defined function
<https://www.postgresql.org/docs/current/static/xfunc.html>`_.
.. autoclass:: Function
.. automethod:: Function.to_map
.. automethod:: Function.create
.. automethod:: Function.alter
.. automethod:: Function.drop
Aggregate Function
------------------
:class:`Aggregate` is derived from :class:`Proc` and represents a
`Postgres user-defined aggregate function
<https://www.postgresql.org/docs/current/static/sql-createaggregate.html>`_.
.. autoclass:: Aggregate
.. automethod:: Aggregate.to_map
.. automethod:: Aggregate.create
Procedure Dictionary
--------------------
:class:`ProcDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of regular and aggregate functions in a
database.
.. autoclass:: ProcDict
.. automethod:: ProcDict.from_map
+132
View File
@@ -0,0 +1,132 @@
Pyrseas
=======
Pyrseas provides utilities to describe a PostgreSQL database schema as
YAML, to verify the schema against the same or a different database
and to generate SQL that will modify the schema to match the YAML
description.
Features
--------
- Outputs a YAML/JSON description of a PostgreSQL database's tables
and other objects (metadata), suitable for storing in a version
control repository
- Generates SQL statements to modify a database so that it will match
an input YAML/JSON specification
- Generates an augmented YAML description of a PostgreSQL database
from its catalogs and an augmentation specification.
Requirements
------------
- `PostgreSQL <https://www.postgresql.org/>`_ 10 or higher
- `Python <https://www.python.org/>`_ 3.7 or higher
- `Psycopg3 <https://www.psycopg.org/psycopg3/>`_ 3.1 or higher
- `PyYAML <https://pyyaml.org/>`_ 5.3 or higher
Contents
--------
.. toctree::
:maxdepth: 2
overview
install
config
configitems
devel
testing
issues
predefaug
.. toctree::
:maxdepth: 1
dbaugment
dbtoyaml
yamltodb
cmdargs
.. _api-ref:
API Reference
-------------
Currently, the only external APIs are the class
:class:`~pyrseas.database.Database` and the methods
:meth:`~pyrseas.database.Database.to_map` and
:meth:`~pyrseas.database.Database.diff_map` of the latter. Other
classes and methods are documented mainly for developer use.
.. toctree::
:maxdepth: 2
dbobject
database
schema
Non-schema Objects
~~~~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 2
cast
eventtrig
extension
foreign
language
Tables and Related Objects
~~~~~~~~~~~~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 2
table
column
constraint
indexes
rule
Functions, Operators and Triggers
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 2
function
operator
operfamily
operclass
trigger
Types and Other Schema Objects
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. toctree::
:maxdepth: 2
collation
conversion
textsearch
type
Augmenter API Reference
-----------------------
.. toctree::
:maxdepth: 2
augmentdb
cfgobjects
augobjects
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
+43
View File
@@ -0,0 +1,43 @@
Indexes
=======
.. module:: pyrseas.dbobject.index
The :mod:`index` module defines two classes, :class:`Index` and
:class:`IndexDict`, derived from :class:`DbSchemaObject` and
:class:`DbObjectDict`, respectively.
Index
-----
Class :class:`Index` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents an index on a
database table, other than a primary key or unique constraint
index. Its :attr:`keylist` attributes are the schema name, the table
name and the index name. Note that index names are supposed to be
unique with a given schema so the table name doesn't have to be part
of the :attr:`keylist`, but has been retained to facilitate certain
operations.
.. autoclass:: Index
.. automethod:: Index.key_expressions
.. automethod:: Index.to_map
.. automethod:: Index.create
.. automethod:: Index.alter
.. automethod:: Index.drop
Index Dictionary
----------------
Class :class:`IndexDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict` and represents the collection
of indexes in a database.
.. autoclass:: IndexDict
.. automethod:: IndexDict.from_map
+182
View File
@@ -0,0 +1,182 @@
Installation
============
Summary
-------
For the latest release, use::
pip install Pyrseas
For development::
git clone git://github.com/perseas/Pyrseas.git
cd Pyrseas
python setup.py install
Requirements
------------
Pyrseas provides tools for `Postgres <https://www.postgresql.org>`_,
so obviously you need **Postgres** to start with. Pyrseas has been
tested with PG 10, 11, 12 and 13 and we'll certainly keep up
with future releases. Please refer to the `Postgres download page
<https://www.postgresql.org/download>`_ to find a distribution for the
various Linux, Unix and Windows platforms supported.
You will also need **Python**. Pyrseas was originally developed using
`Python <http://www.python.org>` 2 and then ported to Python 3 and
tested against versions from 3.7 through 3.9. On Linux or \*BSD,
Python may already be part of your distribution or may be available as
a package. For Windows and Mac OS please refer to the `Python
download page <http://www.python.org/downloads/>`_ for installers and
instructions.
Pyrseas talks to the Postgres DBMS via the **Psycopg adapter**.
Pyrseas has been tested with `psycopg <https://www.psycopg.org/psycopg3/>`_
3.1. Psycopg may be available as a package on most Linux or
\*BSD distributions and can also be downloaded or installed from PyPI.
Please refer to the `Psycopg download page
<http://www.psycopg.org/psycopg3/docs/basic/install.html>`_ for more details.
.. note:: If you install Pyrseas using ``pip`` (see below) and you
have not already installed Psycopg, e.g., when installing into a
``virtualenv`` environment created with ``--no-site-packages``, you
may need to have installed the Postgres and Python development
packages, and a C compiler, as ``pip`` may download and attempt to
build and install psycopg before installing Pyrseas.
The Pyrseas utilities rely on **PyYAML**, a `YAML <https://yaml.org>`_
library. This may be available as a package for your operating system
or it can be downloaded from the `Python Package Index (PyPI)
<https://pypi.org/project/PyYAML/>`_.
.. _download:
Downloading
-----------
Pyrseas is available at the following locations:
- `Python Package Index <https://pypi.org/project/Pyrseas>`_
- `Postgres Extension Network (PGXN) <https://pgxn.org/dist/pyrseas/>`_
- `GitHub repository <https://github.com/perseas/Pyrseas>`_
You can download the distribution from PyPI in gzip-compressed tar or
ZIP archive format, but you can download *and* install it using
``Pip``. See `Python Installer`_ below for details.
PGXN provides a ZIP archive which you can download or you can download
*and* install using the PGXN client (see `PGXN Client`_ below).
The GitHub repository holds the Pyrseas source code, tagged according
to the various releases, e.g., v0.9.0, and including unreleased
modifications. To access it, you need `Git <https://git-scm.com/>`_
which is available as a package in most OS distributions or can be
downloaded from the `Git download page
<https://git-scm.com/download>`_. You can fetch the Pyrseas sources by
issuing the following command::
git clone https://github.com/perseas/Pyrseas.git
This will create a ``Pyrseas`` directory tree (you can use a different
target name by adding it to the above commands). To list available
releases, change to the subdirectory and invoke ``git tag``. To
switch to a particular release, use::
git checkout vn.n.n
where *vn.n.n* is the release identifier. Use ``git checkout master``
to revert to the main (master) branch. To fetch the latest updates,
use::
git pull
Installation
------------
Extracting Sources
~~~~~~~~~~~~~~~~~~
Once you have downloaded an archive from PyPI or PGXN, you need to
extract the sources. For a gzip-compressed tar file, use::
tar xzf Pyrseas-n.n.n.tar.gz
where *n.n.n* is the release version. For a ZIP archive, use::
unzip Pyrseas-n.n.n.zip
Both commands above will create a directory ``Pyrseas-n.n.n`` and you
will want to ``cd`` to it before proceeding with the installation.
Installing
~~~~~~~~~~
If you have superuser or similar administrative privileges, you can
install Pyrseas for access by multiple users on your system. On Linux
and other Unix-flavored systems, you can install from the extracted
``Pyrseas-n.n.n`` source directory or from the root directory of the
``git`` clone, using the following command::
sudo python setup.py install
That will install the :doc:`dbtoyaml </dbtoyaml>` and :doc:`yamltodb
</yamltodb>` utility scripts in a directory such as
``/usr/local/bin``. The library sources and bytecode files will be
placed in a ``pyrseas`` subdirectory under ``site-packages`` or
``dist-packages``, e.g.,
``/usr/local/lib/python3.6/dist-packages/pyrseas``.
On Windows, from an account with Administrator privileges, you can
use::
python setup.py install
That will install the Pyrseas utilities in the ``Scripts`` folder of
your Python installation. The source and bytecode files will go in
the ``site-packages`` folder, e.g.,
``C:\Python37\Lib\site-packages\pyrseas``.
.. _installer:
Python Installer
~~~~~~~~~~~~~~~~
You can also download and install Pyrseas using `pip
<https://pypi.org/project/pip/>`_. For example, on Linux do::
sudo pip install Pyrseas
If this is the first time you are installing a Python package, please
do yourself a favor and read and follow the instructions in the
"Distribute & Pip" subsection of the "Installing Python on ..."
section for your platform of the `The Hitchhikers Guide to Python!
<http://docs.python-guide.org/en/latest/index.html>`_.
.. note:: On FreeBSD, it has been reported that it is necessary to
install the Python ``distribute`` package, prior to
installing Pyrseas with ``pip``. This may also be necessary
on other BSD variants.
.. note:: On Windows 64-bit, it has been reported that it is necessary
to obtain unofficial versions of the ``distribute`` and
``PyYAML`` packages, available at `University of California,
Irvine <https://www.lfd.uci.edu/~gohlke/pythonlibs/>`_. For
a detailed tutorial, see `this post
<http://dbadailystuff.com/2012/07/04/install-pyrseas-in-windows/>`_.
``Pip`` can also be used in a Python `virtualenv
<http://virtualenv.pypa.io/en/latest/>`_ environment, in which case
you *don't* need to prefix the commands with ``sudo``.
``Pip`` also provides the ability to uninstall Pyrseas.
PGXN Client
~~~~~~~~~~~
The PGXN `client <https://pypi.org/project/pgxnclient/>`_ (available
at PyPI) can be used to download and install Pyrseas from PGXN. Usage
is::
pgxn install pyrseas
+114
View File
@@ -0,0 +1,114 @@
Known Issues
============
The following summarizes notable deficiencies in the current release
of the Pyrseas utilities. For further details please refer to the
discussions in the `Pyrseas issue tracker
<https://github.com/perseas/Pyrseas/issues>`_. Suggestions or patches
to deal with these issues are welcome.
Coverage of Postgres Objects
----------------------------
An important Pyrseas objective is to support creating, altering or
dropping nearly any Postgres object accessible through SQL, including
adding, modifying or removing any attributes or features of those
objects. At present, we believe Pyrseas covers roughly over 90% of
the Postgres object/attribute universe. Please refer to the `Feature
Matrix <https://pyrseas.wordpress.com/feature-matrix/>`_ for details.
This is a continuing effort since Postgres keeps adding new features
in each release, such as the table PARTITIONING syntax in PG 10. We
have documented current limitations in the issue tracker, see, for
example, issues `135 <https://github.com/perseas/Pyrseas/issues/135>`_
and `178 <https://github.com/perseas/Pyrseas/issues/178>`_. Please
open an issue on the tracker if you find objects or features needing
additional support.
Object Dependencies
-------------------
The first releases of :program:`yamltodb` used a generally fixed
traversal order when generating SQL. This caused problems with
complex dependencies between objects (e.g., views that depended on
functions that depended on types). Release 0.8 introduced a
topological sort of objects based on their dependencies. The
resulting dependency graph is now used to drive SQL generation. This
should eliminate most object dependency problems seen with the
previous architecture. However, certain issues still remain.
Specifically, if an object depends on a Postgres internally-defined
object, or on an object defined by a Postgres extension, the Pyrseas
utilities may not behave as expected (see issue `175
<https://github.com/perseas/Pyrseas/issues/175>`_ for additional
discussion).
Object renaming
---------------
Pyrseas provides support for generating SQL statements to rename
various database objects, e.g., ALTER TABLE t1 RENAME TO t2, using an
'oldname' tag which can be added to objects that support SQL RENAME.
The tag has to be added manually to a YAML specification for yamltodb
to act on it and cannot be kept in the YAML file for subsequent runs.
This is not entirely satisfactory for storing the YAML file in a
version control system.
Memory utilization
------------------
The yamltodb utility compares the existing and input metadata by
constructing parallel, in-memory representations of the database
catalogs and the input YAML specification. If the database has a
large number of objects, e.g., in the thousands of tables, the
utility's memory usage may be noticeable.
Multiline Strings
-----------------
The text of function source code, view definitions or object COMMENTs
present a problem when they span multiple lines. The default YAML
output format is to enclose the entire string in double quotes, to
show newlines that are part of the text as escaped characters (i.e.,
``\n``) and to break the text into lines with a
backslash-newline-indentation-backslash pattern. For example::
source: "\n SELECT inventory_id\n FROM inventory\n WHERE film_id =\
\ $1\n AND store_id = $2\n AND inventory_in_stock(inventory_id);\n"
This is not very readable, but it does allow YAML to read it back and
correctly reconstruct the original string. To improve readability,
Pyrseas 0.7 introduced special processing for these strings. By using
YAML notation, the same string is represented as follows::
source: |2
SELECT inventory_id
FROM inventory
WHERE film_id = $1
AND store_id = $2
AND NOT inventory_in_stock(inventory_id);
Note also that if your function source code has trailing spaces at the
end of lines, they would normally be represented in the original
default format. However, in the interest of readability,
:program:`dbtoyaml` will remove the trailing spaces from the text.
Index and Partitioning Expressions
----------------------------------
Postgres allows users to create `indexes using expressions
<https://www.postgresql.org/docs/current/static/indexes-expressional.html>`_.
A user can also mix expressions with regular columns. The Postgres
catalogs store the index information in a bespoke fashion: an array of
column numbers where a zero indicates an expression and a list of
expression trees (an internal format) for the expressions, with
additional arrays for collation information, operator classes and
index options such as ``ASC`` or ``DESC``. Although the
``pg_get_indexdef`` system catalog function can be used to obtain a
full ``CREATE INDEX`` statement, Pyrseas has chosen to specify each
column or expression separately in the YAML definitions. This has
not been satisfactory in complex cases (see for example issue `170
<https://github.com/perseas/Pyrseas/issues/170>`_) and is an area
requiring further attention. A similar situation exists for table
partitioning using expressions.
+35
View File
@@ -0,0 +1,35 @@
Procedural Languages
====================
.. module:: pyrseas.dbobject.language
The :mod:`language` module defines two classes, :class:`Language` and
:class:`LanguageDict`, derived from :class:`DbObject` and
:class:`DbObjectDict`, respectively.
Procedural Language
-------------------
:class:`Language` is derived from :class:`~pyrseas.dbobject.DbObject`
and represents a procedural language.
.. autoclass:: Language
.. automethod:: Language.to_map
.. automethod:: Language.drop
.. automethod:: Language.create
Language Dictionary
-------------------
:class:`LanguageDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of procedural languages in a
database. Internal languages ('internal', 'c' and 'sql') are excluded.
.. autoclass:: LanguageDict
.. automethod:: LanguageDict.from_map
+36
View File
@@ -0,0 +1,36 @@
Operators
=========
.. module:: pyrseas.dbobject.operator
The :mod:`operator` module defines two classes: class
:class:`Operator` derived from :class:`DbSchemaObject` and class
:class:`OperatorDict` derived from :class:`DbObjectDict`.
Operator
---------
:class:`Operator` is derived from :class:`DbSchemaObject` and
represents a `Postgres user-defined operator
<https://www.postgresql.org/docs/current/static/xoper.html>`_.
.. autoclass:: Operator
.. automethod:: Operator.extern_key
.. automethod:: Operator.qualname
.. automethod:: Operator.identifier
.. automethod:: Operator.create
Operator Dictionary
-------------------
:class:`OperatorDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of operators in a database.
.. autoclass:: OperatorDict
.. automethod:: OperatorDict.from_map
+36
View File
@@ -0,0 +1,36 @@
Operator Classes
================
.. module:: pyrseas.dbobject.operclass
The :mod:`operclass` module defines two classes: class
:class:`OperatorClass` derived from :class:`DbSchemaObject` and class
:class:`OperatorClassDict` derived from :class:`DbObjectDict`.
Operator Class
--------------
:class:`OperatorClass` is derived from :class:`DbSchemaObject` and
represents a `Postgres operator class
<https://www.postgresql.org/docs/current/static/sql-createopclass.html>`_.
.. autoclass:: OperatorClass
.. automethod:: OperatorClass.extern_key
.. automethod:: OperatorClass.identifier
.. automethod:: OperatorClass.to_map
.. automethod:: OperatorClass.create
Operator Class Dictionary
-------------------------
:class:`OperatorClassDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of operator classes in a database.
.. autoclass:: OperatorClassDict
.. automethod:: OperatorClassDict.from_map
+35
View File
@@ -0,0 +1,35 @@
Operator Families
=================
.. module:: pyrseas.dbobject.operfamily
The :mod:`operfamily` module defines two classes: class
:class:`OperatorFamily` derived from :class:`DbSchemaObject` and class
:class:`OperatorFamilyDict` derived from :class:`DbObjectDict`.
Operator Family
---------------
:class:`OperatorFamily` is derived from :class:`DbSchemaObject` and
represents a `Postgres operator family
<https://www.postgresql.org/docs/current/static/sql-createopfamily.html>`_,
a grouping of related operator classes.
.. autoclass:: OperatorFamily
.. automethod:: OperatorFamily.extern_key
.. automethod:: OperatorFamily.identifier
.. automethod:: OperatorFamily.create
Operator Family Dictionary
--------------------------
:class:`OperatorFamilyDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of operator families in a database.
.. autoclass:: OperatorFamilyDict
.. automethod:: OperatorFamilyDict.from_map
+117
View File
@@ -0,0 +1,117 @@
.. -*- coding: utf-8 -*-
Overview
========
Pyrseas provides utilities to maintain a `PostgreSQL
<https://www.postgresql.org/>`_ database schema. Its purpose is to
enhance and follow through on the concepts of the `Andromeda Project
<http://www.andromeda-project.org/>`_.
Whereas Andromeda expects the database designer or developer to
provide a single `YAML <http://yaml.org/>`_ specification file of the
database to be created, Pyrseas allows the development database to be
created using the familiar SQL CREATE statements. The developer can
then run the `dbtoyaml` utility to generate the YAML specification
from the database. The spec can then be stored in any desired version
control (VCS) repository. Similarly, she can add columns or modify
tables or other objects using SQL ALTER statements and regenerate the
YAML spec with dbtoyaml.
When ready to create or upgrade a test or production database, the
`yamltodb` utility can be used with the YAML spec as input, to generate
a script of SQL CREATE or ALTER statements to modify the database so
that it matches the input spec.
A third tool, `dbaugment`, can be used to add custom attributes and
supporting objects to a given schema. For example, an `updated`
column can be added to various tables, together with trigger functions
to ensure the columns are automatically modified as changes are made.
Use Cases
---------
The following sections discuss the main scenarios where Pyrseas
tools may be helpful.
Version Control
---------------
The case for implementing a tool to facilitate version control over
SQL databases was made in a couple of blog posts: `Version
Control, Part 1: Pre-SQL
<https://pyrseas.wordpress.com/2011/02/01/version-control-part-i-pre-sql/>`_
and `Version Control, Part 2: SQL Databases
<https://pyrseas.wordpress.com/2011/02/07/version-control-part-2-sql-databases/>`_. In
summary, SQL data definition commands are generally incompatible with
traditional version control approaches which usually require
comparisons (diffs) between revisions of source files.
A refinement of the approach described in the aforementioned blog
posts will be of interest to users with many objects in their database
schemas, i.e., many tables, views, functions, and other more complex
objects. Instead of storing a complete database specification in a
single YAML file, by using the `--multiple-files` option to
:program:`dbtoyaml`, the specification can be broken down into files
corresponding, generally, to a single database object. This allows a
VCS **diff** facility to easily highlight database changes. Please
refer to the :doc:`dbtoyaml` and :doc:`yamltodb` utilities for further
details.
The Pyrseas version control tools are not designed to be the ultimate
SQL database version control solution. Instead, they are aimed at
assisting two or more developers or DBAs in sharing changes to the
underlying database as they implement a database application. The
sharing can occur through a distributed or centralized VCS. The
Pyrseas tools may even be used by a single DBA in conjunction with a
distributed VCS to quickly explore alternative designs. The tools can
also help to share changes with a conventional QA team, but may
require additional controls for final releases and production
installations.
Supplementary Actions
---------------------
In many instances, a database schema needs to be supplemented by
rarely-modified data kept in certain tables, e.g., a
codes-descriptions table. The data import and export features,
controlled by `datacopy` configuration parameter (see
:doc:`configitems` for details) facilitates this need.
In other cases, DBAs may want to standardize certain additional table
columns or processing. For example, they may want to capture the user
and time of modification of a certain set of tables using a common
procedure. The :doc:`dbaugment` utility was introduced to support
these needs.
Generating SQL by determining what changed between one schema version
and another is sometimes not sufficient. Although the change may be
as simple as adding a column to a table and adding a referential
constraint to the new column, if the tables already have data, it may
not be possible to run the SQL generated by :program:`yamltodb`. This
requires manual intervention by the DBAs or developers. The project
would like to assist with these types of changes. The blog post `The
Future of Pyrseas: Part 1
<https://pyrseas.wordpress.com/2016/06/09/the-future-of-pyrseas-part-1/>`_
is a first step in discussing this requirement.
Naming
------
The project name comes from `Python <https://www.python.org/>`_, the
programming language, and `Perseas
<https://en.wikipedia.org/wiki/Perseus>`_ [#]_, the Greek mythological
hero who rescued Andromeda from a sea monster [#]_. It is hoped that
Pyrseas will rescue the Andromeda project <grin>. You can pronounce
Pyrseas like the hero.
.. rubric:: Footnotes
.. [#] The common English name for Perseas is Perseus and the Ancient
Greek name is Perseos. However, in modern Greek Περσέας_ is the
more common spelling for the mythical hero.
.. _Περσέας: https://en.wiktionary.org/wiki/%CE%A0%CE%B5%CF%81%CF%83%CE%AD%CE%B1%CF%82
.. [#] He is better known for having killed Medusa.
+93
View File
@@ -0,0 +1,93 @@
.. _predef-aug:
Predefined Database Augmentations
=================================
These augmentations are specified in the ``config.yaml`` configuration
file distributed with Pyrseas' :program:`dbaugment`.
Columns
-------
These are predefined column specifications that can be added to
tables, e.g., in various audit column combinations (see `Audit
Columns`_ below).
- created_by_ip_address: An INET column to record the IP address which
originated the current row.
- created_by_user: A VARCHAR(63) column to record the user, e.g.,
CURRENT_USER, who created the current row.
- created_date: A DATE column that defaults to CURRENT_DATE.
- created_timestamp: A TIMESTAMP WITH TIME ZONE column to record the
date and time when the current row was created.
- modified_by_ip_address: An INET column to record the IP address
which originated the last modification to the current row.
- modified_by_user: A VARCHAR(63) column to record the user, e.g.,
CURRENT_USER, who last modified the current row.
- modified_timestamp: A TIMESTAMP WITH TIME ZONE column to record the
date and time when the current row was last modified.
Functions
---------
The following are predefined trigger functions which are used to
implement various augmentations. The source for each function,
written in PL/pgSQL, is specified in a function template, named with a
``functempl_`` prefixed to the function name.
- Audit when modified (``audit_modified``): This function provides the
CURRENT_TIMESTAMP value for audit columns.
- Default audit (``audit_default``): This function provides the
CURRENT_USER and CURRENT_TIMESTAMP for audit columns.
- Full audit (``audit_full``): For SQL INSERTs, this function provides
values for the user who created the row, the CURRENT_TIMESTAMP and
the IP address for both the ``created_`` and ``modified_`` audit
columns. For UPDATEs, it retains the existing values in the
``created_`` columns and supplies current values for the
``modified_`` columns.
In addition, the following helper functions are defined in schema
``pyrseas``:
- get_session_variable
- set_session_variable
A variant of ``get_session_variable`` is invoked by the ``audit_full``
function to retrieve the actual (logged-on) user and IP address. In
web applications, the user that connects to the database is typically
the system user running the web server, rather than the application
(logged on) user. The application can invoke the
``pyrseas.set_session_variable`` function to supply the application
user and IP address so that the audit trail will reflect the
application context corrrectly.
Audit Columns
-------------
These are predefined combinations of columns to be added to tables to
record audit trail information. They may also include triggers to be
invoked to maintain the column values.
- created_date_only: This is the simplest audit trail that adds a
``created_date`` column which defaults to the CURRENT_DATE.
- modified_only: This is another simple audit trail. It adds a
``modified_timestamp`` column which is supplied by a trigger named
`table_name`\_20_audit_modified_only.
- default: This is the default for audit columns. It adds the columns
``modified_by_user`` and ``modified_timestamp`` and a trigger named
`table_name`\_20_audit_default to fill in the columns.
- full: This is the most extensive audit trail combination. It adds
``created_`` and ``modified_`` columns for user, IP address and
timestamp. It also adds a trigger named
`table_name`\_20_audit_full.
+35
View File
@@ -0,0 +1,35 @@
Rules
=====
.. module:: pyrseas.dbobject.rule
The :mod:`rule` module defines two classes, :class:`Rule` and
:class:`RuleDict`, derived from :class:`DbSchemaObject` and
:class:`DbObjectDict`, respectively.
Rule
----
:class:`Rule` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a `Postgres
rewrite rule
<https://www.postgresql.org/docs/current/static/rules.html>`_.
.. autoclass:: Rule
.. automethod:: Rule.identifier
.. automethod:: Rule.to_map
.. automethod:: Rule.create
Rule Dictionary
---------------
:class:`RuleDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of rewrite rules in a database.
.. autoclass:: RuleDict
.. automethod:: RuleDict.from_map
+57
View File
@@ -0,0 +1,57 @@
Schemas
=======
.. module:: pyrseas.dbobject.schema
The :mod:`schema` module defines two classes, :class:`Schema` and
:class:`SchemaDict`, derived from :class:`DbObject` and
:class:`DbObjectDict`, respectively.
Schema
------
:class:`Schema` is derived from :class:`~pyrseas.dbobject.DbObject`
and represents a database schema or Postgres namespace, i.e., a
collection of tables and other objects. The 'public' schema is
currently treated specially as in most contexts an unqualified object
is assumed to be part of it, e.g., table "t" is usually shorthand for
table "public.t." The 'pyrseas' schema, if present, is excluded as it
is only intended for use by :program:`dbaugment` or other Pyrseas
internal purposes.
.. autoclass:: Schema
.. automethod:: Schema.extern_dir
.. automethod:: Schema.to_map
.. automethod:: Schema.create
.. automethod:: Schema.drop
.. automethod:: Schema.data_import
Schema Dictionary
-----------------
:class:`SchemaDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of schemas in a database. Certain internal
schemas (information_schema, pg_catalog, etc.) owned by the 'postgres'
user are excluded.
.. autoclass:: SchemaDict
Method :meth:`from_map` is called from :class:`Database`
:meth:`~pyrseas.database.Database.from_map` to start a recursive
interpretation of the input map. The :obj:`inmap` argument is the same
as input to the :meth:`~pyrseas.database.Database.diff_map` method of
:class:`Database`. The :obj:`newdb` argument is the holder of
:class:`~pyrseas.dbobject.DbObjectDict`-derived dictionaries which is
filled in as the recursive interpretation proceeds.
.. automethod:: SchemaDict.from_map
.. automethod:: SchemaDict.to_map
.. automethod:: SchemaDict.data_import
+178
View File
@@ -0,0 +1,178 @@
Tables, Views and Sequences
===========================
.. module:: pyrseas.dbobject.table
The :mod:`table` and :mod:`view` modules define six classes,
:class:`DbClass` derived from :class:`DbSchemaObject`, classes
:class:`Sequence`, :class:`Table` and :class:`View` derived from
:class:`DbClass`, :class:`MaterializedView` derived from
:class:`View`, and :class:`ClassDict`, derived from
:class:`DbObjectDict`.
Database Class
--------------
Class :class:`DbClass` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a table, view
or sequence as defined in the Postgres `pg_class` catalog.
.. autoclass:: DbClass
Sequence
--------
Class :class:`Sequence` is derived from :class:`DbClass` and
represents a `sequence generator
<https://www.postgresql.org/docs/current/static/sql-createsequence.html>`_.
Its :attr:`keylist` attributes are the schema name and the sequence
name.
The map returned by :meth:`to_map` and expected as argument by
:meth:`ClassDict.from_map` has the following structure::
{'sequence seq1':
{'cache_value': 1,
'data_type': 'integer',
'increment_by': 1,
'max_value': None,
'min_value': None,
'owner_column': 'c1',
'owner_table': 't1',
'start_value': 1
}
}
.. autoclass:: Sequence
.. automethod:: Sequence.get_attrs
.. automethod:: Sequence.get_dependent_table
.. automethod:: Sequence.to_map
.. automethod:: Sequence.create
.. automethod:: Sequence.add_owner
.. automethod:: Sequence.alter
.. automethod:: Sequence.drop
Table
-----
Class :class:`Table` is derived from :class:`DbClass` and represents a
database table. Its :attr:`keylist` attributes are the schema name and
the table name.
The map returned by :meth:`to_map` and expected as argument by
:meth:`ClassDict.from_map` has a structure similar to the following::
{'table t1':
{'columns':
[
{'c1': {'type': 'integer', 'not_null': True}},
{'c2': {'type': 'text'}},
{'c3': {'type': 'smallint'}},
{'c4': {'type': 'date', 'default': 'now()'}}
],
'description': "this is the comment for table t1",
'primary_key':
{'t1_prim_key':
{'columns': ['c1', 'c2']}
},
'foreign_keys':
{'t1_fgn_key1':
{'columns': ['c2', 'c3'],
'references':
{'table': 't2', 'columns': ['pc2', 'pc1']}
},
't1_fgn_key2':
{'columns': ['c2'],
'references': {'table': 't3', 'columns': ['qc1']}
}
},
'unique_constraints': {...},
'indexes': {...}
}
}
The values for :obj:`unique_constraints` and :obj:`indexes` follow a
pattern similar to :obj:`primary_key`, but there can be more than one
such specification.
.. autoclass:: Table
.. automethod:: Table.column_names
.. automethod:: Table.to_map
.. automethod:: Table.create
.. automethod:: Table.drop
.. automethod:: Table.diff_options
.. automethod:: Table.alter
.. automethod:: Table.alter_drop_columns
.. automethod:: Table.data_export
.. automethod:: Table.data_import
Class Dictionary
----------------
Class :class:`ClassDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict` and represents the collection
of tables, views and sequences in a database.
.. autoclass:: ClassDict
.. automethod:: ClassDict.from_map
.. module:: pyrseas.dbobject.view
View
----
Class :class:`View` is derived from :class:`DbClass` and represents a
database view. Its :attr:`keylist` attributes are the schema name and
the view name.
The map returned by :meth:`to_map` and expected as argument by
:meth:`ClassDict.from_map` has a structure similar to the following::
{'view v1':
{'columns': [{'c1': {'type': 'integer'}},
{'c2': {'type': 'date'}}],
'definition': " SELECT ...;",
'description': "this is the comment for view v1"
}
}
.. autoclass:: View
.. automethod:: View.to_map
.. automethod:: View.create
.. automethod:: View.alter
Materialized View
-----------------
Class :class:`MaterializedView` is derived from :class:`View` and
represents a `materialized view
<https://www.postgresql.org/docs/current/static/sql-creatematerializedview.html>`_. Its
:attr:`keylist` attributes are the schema name and the view name.
.. autoclass:: MaterializedView
.. automethod:: MaterializedView.to_map
.. automethod:: MaterializedView.create
+175
View File
@@ -0,0 +1,175 @@
.. _testing:
Testing
=======
The majority of Pyrseas' capabilities are exercised and verified via
unit tests written using `pytest
<https://docs.pytest.org/en/latest/>`_. The tests can be run from the
command line by most users, e.g.,
::
pytest-3 tests/dbobject/test_table.py
pytest-3 tests/dbobject/test_trigger.py -k test_create_trigger
pytest-3 tests/functional
The first ``pytest-3`` command above runs all tests related to tables,
mapping, creating, dropping, etc. The second one executes a single
test to generate SQL to create a trigger. The third runs all the
functional tests. Please review the `pytest documentation
<https://docs.pytest.org/en/latest/usage.html>`_ for further options.
Environment Variables
---------------------
By default, the tests use a Postgres database named ``pyrseas_testdb``
which is created if it doesn't already exist. The tests are run as the
logged in user, using the ``USER`` Unix/Linux environment variable (or
``USERNAME`` under Windows). They access Postgres on the local host
using the default port number (5432).
The following four environment variables can be used to change the
defaults described above:
- PYRSEAS_TEST_DB
- PYRSEAS_TEST_USER
- PYRSEAS_TEST_HOST
- PYRSEAS_TEST_PORT
Restrictions
------------
Unless the test database exists and the user running the tests has
access to it, the user role will need CREATEDB privilege.
Most tests do not require special privileges. However, certain tests
may require Postgres SUPERUSER privilege. Such tests will normally be
skipped if the user lacks the privilege.
Most tests do not require installation of supporting Postgres
packages. However, a few tests rely on the availability of Postgres
``contrib`` modules such as the `spi module
<https://www.postgresql.org/docs/current/static/contrib-spi.html>`_ or
procedural languages such as ``plperl``, ``plpython3u`` or ``plr``.
On Windows, it is necessary to install Perl in order to run some of
the tests (most Linux or Unix variants already include it as part of
their normal distribution). The last time we checked, a suitable
choice appeared to be Strawberry Perl which can be downloaded from
http://strawberryperl.com/releases.html. However, the default
installation is placed in ``C:\strawberry`` and can hold a single Perl
version. Furthermore, some Postgres versions may be linked with
non-current Perl versions. It is recommended that the latest Perl
version be installed as this will usually give the fewest test
failures. See `this blog post
<https://pyrseas.wordpress.com/2012/10/17/testing-python-and-postgresql-on-windows-part-5/>`_
for more details.
The COLLATION tests require the
``fr_FR.utf8`` locale (or ``French.France.1252`` language on Windows)
to be installed.
Testing Checklist
-----------------
The following is a summary list of steps needed to test Pyrseas on a
new machine. Refer to :ref:`development` for details on how to
accomplish a given installation task. "Package manager" refers to the
platform's package management system utility such as ``apt-get`` or
``yum``. Installation from PyPI can be done with ``pip``. Some
operations require administrative or superuser privileges, at either
the operating system or Postgres level.
- Install Git using package manager or from
https://git-scm.com/download (on Windows, prefer Git Bash)
- ``git clone git://github.com/perseas/Pyrseas.git``
- Install Python 3.7 or higher, using package manager or from
installers at https://www.python.org/downloads/.
- Install Postgres 13, 12, 11 or 10, using package manager or
binary installers at https://www.postgresql.org/download/
.. note:: On Linux, make sure you install the contrib and plperl
packages, e.g., on Debian, postgresql-contrib-n and
postgresql-plperl-n (where `n` is the Postgres
version number)
- Install Psycopg, using package manager, or from PyPI
(https://pypi.org/project/psycopg/).
.. note:: On Windows, you may first want to install a version of
Microsoft Visual Studio from `here`_. An alternative
that may work is `MinGW <http://mingw.org/>`_. See
`these blog`_ `posts`_ for more details.
.. _here: https://www.microsoft.com/en-us/download/developer-tools.aspx
.. _these blog: https://pyrseas.wordpress.com/2012/09/25/testing-python-and-postgresql-on-windows-part-2/
.. _posts: https://pyrseas.wordpress.com/2012/09/28/testing-python-and-postgresql-on-windows-part-3/
- Install PyYAML, using package manager, or from PyPI
(https://pypi.org/project/PyYAML/) or
http://pyyaml.org/download/pyyaml/.
- Install pytest, using package manager, or from PyPI
(https://pypi.org/project/pytest/).
- Install Tox, using package manager, or from PyPI
(https://pypi.org/project/tox/)
- On Windows, install Perl (see discussion above under
"Restrictions"). On Linux, usually Perl is already available.
- As **postgres** user, using psql or pgAdmin, create a test user,
e.g., your name. The user running tests must have at a minimum
createdb privilege, in order to create the test database. To run
*all* the tests, the user also needs superuser privilege.
- Create a Postgres password file, e.g., on Linux: ``~/.pgpass``, on
Windows: ``%APPDATA%\postgresql\pgpass.conf``.
- Create directories to hold tablespaces, e.g., ``/extra/pg/13.0/ts1``
on Linux, ``C:\\extra\\pg\\13.0\\ts1`` on Windows. The directories
need to be owned by the **postgres** user. This may be tricky on
older Windows versions, but the command ``cacls <dir> /E /G
postgres:F`` should suffice. Using ``psql``, create tablespaces
**ts1** and **ts2**, e.g., ``CREATE TABLESPACE ts1 LOCATION
'<directory>'`` (on Windows, you'll have to use, e.g.,
``E'C:\\dir\\ts1'``, to specify the directory).
- Install the locale ``fr_FR.utf8`` on Linux/Unix or the language
``French.France.1252`` on Windows.
- On Debian and derivatives, this can be done with the command::
sudo dpkg-reconfigure locales
- On Windows, open the Control Panel, select Date, Time, Language,
and Regional Options, then Regional and Language Options (or Add
other languages), click on the Advanced tab in the dialog and
then choose “French (France)” from the dropdown. Finally, click
OK and respond to any subsequent prompts to install the locale,
including rebooting the machine.
- Change to the Pyrseas source directory (created by the second step above).
- Define the ``PYTHONPATH`` environment variable to the Pyrseas source
directory, e.g., on Linux, ``export PYTHONPATH=$PWD``, on
Windows, ``set PYTHONPATH=%USERPROFILE%\somedir\Pyrseas``.
- Define the ``PG1N0_PORT`` environment variables (where ``1N``
represents the major Posgres version, e.g., 15, 11) to point to the
corresponding Postgres connection ports.
- Invoke ``tox``. This will create virtualenvs in a ``.tox``
subdirectory,
install Pyrseas and its prerequisites (Psycopg and PyYAML) into
each virtualenv and run the unit tests for each combination of
Postgres and Python.
If you find any problems with the instructions above, please open an
issue on `GitHub <https://github.com/perseas/Pyrseas/issues>`_.
+102
View File
@@ -0,0 +1,102 @@
Text Search Objects
===================
.. module:: pyrseas.dbobject.textsearch
The :mod:`textsearch` module defines eight classes: classes
:class:`TSConfiguration`, :class:`TSDictionary`, :class:`TSParser` and
:class:`TSTemplate` derived from :class:`DbSchemaObject`, and classes
:class:`TSConfigurationDict`, :class:`TSDictionaryDict`,
:class:`TSParserDict` and :class:`TSTemplateDict` derived from
:class:`DbObjectDict`.
Text Search Configuration
-------------------------
:class:`TSConfiguration` is derived from :class:`DbSchemaObject` and
represents a `Postgres text search configuration
<https://www.postgresql.org/docs/current/static/sql-createtsconfig.html>`_.
.. autoclass:: TSConfiguration
.. automethod:: TSConfiguration.to_map
.. automethod:: TSConfiguration.create
Text Search Configuration Dictionary
------------------------------------
:class:`TSConfigurationDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of text search configurations in a database.
.. autoclass:: TSConfigurationDict
.. automethod:: TSConfigurationDict.from_map
Text Search Dictionary
----------------------
:class:`TSDictionary` is derived from :class:`DbSchemaObject` and
represents a `Postgres text search dictionary
<https://www.postgresql.org/docs/current/static/textsearch-dictionaries.html>`_.
.. autoclass:: TSDictionary
.. automethod:: TSDictionary.create
Text Search Dictionary Dictionary
---------------------------------
:class:`TSDictionaryDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a Python dictionary
that represents the collection of text search dictionaries in a
database.
.. autoclass:: TSDictionaryDict
.. automethod:: TSDictionaryDict.from_map
Text Search Parser
------------------
:class:`TSParser` is derived from :class:`DbSchemaObject` and
represents a `Postgres text search parser
<https://www.postgresql.org/docs/current/static/sql-createtsparser.html>`_.
.. autoclass:: TSParser
.. automethod:: TSParser.create
Text Search Parser Dictionary
-----------------------------
:class:`TSParserDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of text search parsers in a database.
.. autoclass:: TSParserDict
.. automethod:: TSParserDict.from_map
Text Search Template
--------------------
:class:`TSTemplate` is derived from :class:`DbSchemaObject` and
represents a `Postgres text search template
<https://www.postgresql.org/docs/current/static/sql-createtstemplate.html>`_.
.. autoclass:: TSTemplate
.. automethod:: TSTemplate.create
Text Search Template Dictionary
-------------------------------
:class:`TSTemplateDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of text search templates in a database.
.. autoclass:: TSTemplateDict
.. automethod:: TSTemplateDict.from_map
+35
View File
@@ -0,0 +1,35 @@
Triggers
========
.. module:: pyrseas.dbobject.trigger
The :mod:`trigger` module defines two classes, :class:`Trigger` and
:class:`TriggerDict`, derived from :class:`DbSchemaObject` and
:class:`DbObjectDict`, respectively.
Trigger
-------
:class:`Trigger` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a Postgres
`regular or constraint trigger
<https://www.postgresql.org/docs/current/static/sql-createtrigger.html>`_.
.. autoclass:: Trigger
.. automethod:: Trigger.identifier
.. automethod:: Trigger.to_map
.. automethod:: Trigger.create
Trigger Dictionary
------------------
:class:`TriggerDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of triggers in a database.
.. autoclass:: TriggerDict
.. automethod:: TriggerDict.from_map
+120
View File
@@ -0,0 +1,120 @@
Types and Domains
=================
.. module:: pyrseas.dbobject.dbtype
The :mod:`dbtype` module defines seven classes, :class:`DbType`
derived from :class:`DbSchemaObject`, :class:`BaseType`,
:class:`Composite`, :class:`Enum`, :class:`Domain` and :class:`Range`
derived from :class:`DbType`, and :class:`TypeDict` derived from and
:class:`DbObjectDict`.
Database Type
-------------
Class :class:`DbType` is derived from
:class:`~pyrseas.dbobject.DbSchemaObject` and represents a SQL type or
domain as defined in the Postgres `pg_type` catalog.
.. autoclass:: DbType
Base Type
---------
:class:`BaseType` is derived from :class:`~pyrseas.dbobject.DbType`
and represents a Postgres `user-defined base type
<https://www.postgresql.org/docs/current/static/xtypes.html>`_.
The map returned by :meth:`to_map` and expected as argument by
:meth:`TypeDict.from_map` has the following structure (not all fields
need be present)::
{'type t1':
{'alignment': 'double',
'analyze': 'analyze_func',
'category': 'U',
'delimiter': ',',
'input': 'input_func',
'internallength': 'variable',
'output': 'output_func',
'preferred': 'true',
'receive': 'receive_func',
'send': 'send_func',
'storage': 'plain'
'typmod_in': 'typmod_in_func',
'typmod_out': 'typmod_out_func'
}
}
.. autoclass:: BaseType
.. automethod:: BaseType.to_map
.. automethod:: BaseType.create
.. automethod:: BaseType.drop
Composite
---------
:class:`Composite` is derived from :class:`~pyrseas.dbobject.DbType`
and represents a standalone `composite type
<https://www.postgresql.org/docs/current/static/rowtypes.html>`_.
.. autoclass:: Composite
.. automethod:: Composite.to_map
.. automethod:: Composite.create
.. automethod:: Composite.alter
Enum
----
:class:`Enum` is derived from :class:`~pyrseas.dbobject.DbType` and
represents an `enumerated type
<https://www.postgresql.org/docs/current/static/datatype-enum.html>`_.
.. autoclass:: Enum
.. automethod:: Enum.create
Domain
------
:class:`Domain` is derived from :class:`~pyrseas.dbobject.DbType` and
represents a `domain
<https://www.postgresql.org/docs/current/static/sql-createdomain.html>`_.
.. autoclass:: Domain
.. automethod:: Domain.to_map
.. automethod:: Domain.create
Range
-----
:class:`Range` is derived from :class:`~pyrseas.dbobject.DbType` and
represents a `Postgres range type
<https://www.postgresql.org/docs/current/static/rangetypes.html>`_.
.. autoclass:: Range
.. automethod:: Range.to_map
.. automethod:: Range.create
.. automethod:: Range.alter
Type Dictionary
---------------
:class:`TypeDict` is derived from
:class:`~pyrseas.dbobject.DbObjectDict`. It is a dictionary that
represents the collection of domains and enums in a database.
.. autoclass:: TypeDict
.. automethod:: TypeDict.from_map
+129
View File
@@ -0,0 +1,129 @@
yamltodb - YAML to Database
===========================
Name
----
yamltodb -- generate SQL statements to update a Postgres database to
match the schema specified in a YAML file
Synopsis
--------
::
yamltodb [option...] dbname [spec]
Description
-----------
:program:`yamltodb` is a utility for generating SQL statements to
update a Postgres database so that it will match the schema
specified in an input `YAML <http://yaml.org>`_ formatted
specification file.
For example, given the input file shown under :doc:`dbtoyaml`,
:program:`yamltodb`, when run against a newly-created database,
outputs the following SQL statements::
CREATE SCHEMA s1;
ALTER SCHEMA s1 OWNER TO bob;
GRANT ALL ON SCHEMA s1 TO bob;
GRANT ALL ON SCHEMA s1 TO alice;
CREATE TABLE t1 (
c1 integer NOT NULL,
c2 smallint,
c3 boolean DEFAULT false,
c4 text);
ALTER TABLE t1 OWNER TO alice;
CREATE TABLE s1.t2 (
c21 integer NOT NULL,
c22 character varying(16));
ALTER TABLE s1.t2 OWNER TO bob;
GRANT ALL ON TABLE s1.t2 TO bob;
GRANT SELECT ON TABLE s1.t2 TO PUBLIC;
GRANT INSERT, DELETE, UPDATE ON TABLE s1.t2 TO alice WITH GRANT OPTION;
GRANT INSERT ON TABLE s1.t2 TO carol;
ALTER TABLE t1 ADD CONSTRAINT t1_c2_check CHECK (c2 > 123);
ALTER TABLE t1 ADD CONSTRAINT t1_pkey PRIMARY KEY (c1);
ALTER TABLE s1.t2 ADD CONSTRAINT t2_pkey PRIMARY KEY (c21);
ALTER TABLE t1 ADD CONSTRAINT t1_c2_fkey FOREIGN KEY (c2) REFERENCES s1.t2 (c21);
Options
-------
:program:`yamltodb` accepts the following command-line arguments (in
addition to the :doc:`cmdargs`):
.. program:: yamltodb
**dbname**
Specifies the name of the database whose schema is to analyzed.
**spec**
Specifies the location of the YAML specification. If this is
omitted or specified as a single or double dash, the specification
is read from the program's standard input. However, if the
:option:`--multiple-files` option is used, that takes precedence.
.. cmdoption:: -m, --multiple-files
Specifies that input should be taken from YAML specification files
present in a two-level (metadata) directory tree. See `Multiple
File Output` under :doc:`dbtoyaml` for further details.
.. cmdoption:: -n <schema>
--schema <schema>
Compare only a schema matching `schema`. By default, all schemas
are compared. Multiple schemas can be compared by using multiple
:option:`-n` switches.
.. cmdoption:: -1
--single-transaction
Wrap the generated statements in BEGIN/COMMIT. This ensures that
either all the statements complete successfully, or no changes are
applied.
.. cmdoption:: -u, --update
Execute the generated statements against the database mentioned in
**dbname**. This implies the :option:`--single-transaction`
option.
.. cmdoption:: --revert
Generate SQL in reversion mode, that is, to undo the changes that
would normally be generated. For example, if without this option,
the SQL would be a ``DROP TABLE``, the :option:`--revert` option
generates a ``CREATE TABLE`` with all the columns, constraints and
other objects associated with the table being dropped.
This option is experimental and currently has only been
implemented for schemas and sequences.
Examples
--------
Given a YAML file named ``moviesdb.yaml``, to generate SQL statements
to update a database called `mymovies`::
yamltodb mymovies moviesdb.yaml
To generate the statements as above and immediately update `mymovies`::
yamltodb mymovies moviesdb.yaml | psql mymovies
or::
yamltodb --update mymovies moviesdb.yaml
To generate the statements directly from the output of
:program:`dbtoyaml` (against a different database), with statements
enclosed in a single transaction, and save the statements in a file
named ``mymovies.sql``::
dbtoyaml devmovies | yamltodb -1 mymovies -o mymovies.sql