Skip to content

Commit

Permalink
docs: reformatted README titles (#141)
Browse files Browse the repository at this point in the history
  • Loading branch information
skuruppu committed Nov 10, 2021
1 parent 05aa31e commit a3ccbac
Showing 1 changed file with 25 additions and 28 deletions.
53 changes: 25 additions & 28 deletions README.md
Expand Up @@ -9,8 +9,7 @@ This project has **Preview** release status. Known limitations are listed [here]
- [Cloud Spanner product documentation](https://cloud.google.com/spanner/docs)
- [SQLAlchemy product documentation](https://www.sqlalchemy.org/)

Quick Start
-----------
## Quick Start

In order to use this package, you first need to go through the following steps:

Expand All @@ -19,8 +18,7 @@ In order to use this package, you first need to go through the following steps:
3. [Enable the Google Cloud Spanner API.](https://cloud.google.com/spanner)
4. [Setup Authentication.](https://googleapis.dev/python/google-api-core/latest/auth.html)

Installation
-----------
## Installation

To install an in-development version of the package, clone its Git-repository:
```
Expand All @@ -32,9 +30,9 @@ python setup.py install
```
During setup the dialect will be registered with entry points.

A Minimal App
-----------
**Create a table**
## A Minimal App

### Create a table
```python
from sqlalchemy import (
Column,
Expand All @@ -59,7 +57,8 @@ user = Table(

metadata.create_all(engine)
```
**Insert a row**

### Insert a row
```python
from sqlalchemy import (
MetaData,
Expand All @@ -76,7 +75,7 @@ with engine.begin() as connection:
connection.execute(user.insert(), {"user_id": 1, "user_name": "Full Name"})
```

**Read**
### Read
```python
from sqlalchemy import MetaData, Table, create_engine, select

Expand All @@ -90,16 +89,16 @@ with engine.begin() as connection:
print(row)
```

Migration
-----------
## Migration

SQLAlchemy uses [Alembic](https://alembic.sqlalchemy.org/en/latest/#) tool to organize database migrations.

**Warning!**
A migration script can produce a lot of DDL statements. If each of the statements are executed separately, performance issues can occur. To avoid these, it's highly recommended to use the [Alembic batch context](https://alembic.sqlalchemy.org/en/latest/batch.html) feature to pack DDL statements into groups of statements.

Features and limitations
-----------
**Interleaved tables**
## Features and limitations

### Interleaved tables
Cloud Spanner dialect includes two dialect-specific arguments for `Table` constructor, which help to define interleave relations:
`spanner_interleave_in` - a parent table name
`spanner_inverleave_on_delete_cascade` - a flag specifying if `ON DELETE CASCADE` statement must be used for the interleave relation
Expand All @@ -126,7 +125,7 @@ client = Table(
client.create(engine)
```

**Unique constraints**
### Unique constraints
Cloud Spanner doesn't support direct UNIQUE constraints creation. In order to achieve column values uniqueness UNIQUE indexes should be used.

Instead of direct UNIQUE constraint creation:
Expand All @@ -147,7 +146,7 @@ Table(
Index("uix_1", "col1", unique=True),
)
```
**Autocommit mode**
### Autocommit mode
Spanner dialect supports both `SERIALIZABLE` and `AUTOCOMMIT` isolation levels. `SERIALIZABLE` is the default one, where transactions need to be committed manually. `AUTOCOMMIT` mode corresponds to automatically committing of a query right in its execution time.

Isolation level change example:
Expand All @@ -158,7 +157,7 @@ eng = create_engine("spanner:///projects/project-id/instances/instance-id/databa
autocommit_engine = eng.execution_options(isolation_level="AUTOCOMMIT")
```

**ReadOnly transactions**
### ReadOnly transactions
By default, transactions produced by a Spanner connection are in ReadWrite mode. However, some applications require an ability to grant ReadOnly access to users/methods; for these cases Spanner dialect supports the `read_only` execution option, which switches a connection into ReadOnly mode:
```python
with engine.connect().execution_options(read_only=True) as connection:
Expand All @@ -168,13 +167,13 @@ Note that execution options are applied lazily - on the `execute()` method call,

ReadOnly/ReadWrite mode of a connection can't be changed while a transaction is in progress - first you must commit or rollback it.

**DDL and transactions**
### DDL and transactions
DDL statements are executed outside the regular transactions mechanism, which means DDL statements will not be rolled back on normal transaction rollback.

**Dropping a table**
### Dropping a table
Cloud Spanner, by default, doesn't drop tables, which have secondary indexes and/or foreign key constraints. In Spanner dialect for SQLAlchemy, however, this restriction is omitted - if a table you are trying to delete has indexes/foreign keys, they will be dropped automatically right before dropping the table.

**Data types**
### Data types
Data types table mapping SQLAlchemy types to Cloud Spanner types:

| SQLAlchemy | Spanner |
Expand All @@ -193,14 +192,13 @@ Data types table mapping SQLAlchemy types to Cloud Spanner types:
| NUMERIC | NUMERIC |


**Other limitations**
### Other limitations
- WITH RECURSIVE statement is not supported.
- Named schemas are not supported.
- Temporary tables are not supported, real tables are used instead.
- Numeric type dimensions (scale and precision) are constant. See the [docs](https://cloud.google.com/spanner/docs/data-types#numeric_types).

Best practices
-----------
## Best practices
When a SQLAlchemy function is called, a new connection to a database is established and a Spanner session object is fetched. In case of connectionless execution these fetches are done for every `execute()` call, which can cause a significant latency. To avoid initiating a Spanner session on every `execute()` call it's recommended to write code in connection-bounded fashion. Once a `Connection()` object is explicitly initiated, it fetches a Spanner session object and uses it for all the following calls made on this `Connection()` object.

Non-optimal connectionless use:
Expand All @@ -216,8 +214,8 @@ with engine.begin() as connection:
```
Connectionless way of use is also deprecated since SQLAlchemy 2.0 and soon will be removed (see in [SQLAlchemy docs](https://docs.sqlalchemy.org/en/14/core/connections.html#connectionless-execution-implicit-execution)).

Running tests
------------
## Running tests

Spanner dialect includes a compliance, migration and unit test suite. To run the tests the `nox` package commands can be used:
```
# Run the whole suite
Expand All @@ -226,11 +224,10 @@ $ nox
# Run a particular test session
$ nox -s migration_test
```
**Running tests on Spanner emulator**
### Running tests on Spanner emulator
The dialect test suite can be runned on [Spanner emulator](https://cloud.google.com/spanner/docs/emulator). Several tests, relating to `NULL` values of data types, are skipped when executed on emulator.

Contributing
------------
## Contributing

Contributions to this library are welcome and encouraged. Please report issues, file feature requests, and send pull requests. See [CONTRIBUTING](https://github.com/cloudspannerecosystem/python-spanner-sqlalchemy/blob/main/contributing.md) for more information on how to get
started.
Expand Down

0 comments on commit a3ccbac

Please sign in to comment.