| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,38 @@ | |||
| 1 | + # python3 | ||
| 2 | + # Copyright 2018 Google LLC | ||
| 3 | + # | ||
| 4 | + # Licensed under the Apache License, Version 2.0 (the "License"); | ||
| 5 | + # you may not use this file except in compliance with the License. | ||
| 6 | + # You may obtain a copy of the License at | ||
| 7 | + # | ||
| 8 | + # https://www.apache.org/licenses/LICENSE-2.0 | ||
| 9 | + # | ||
| 10 | + # Unless required by applicable law or agreed to in writing, software | ||
| 11 | + # distributed under the License is distributed on an "AS IS" BASIS, | ||
| 12 | + # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| 13 | + # See the License for the specific language governing permissions and | ||
| 14 | + # limitations under the License. | ||
| 15 | + | ||
| 16 | + from spanner_orm import api | ||
| 17 | + from spanner_orm import condition | ||
| 18 | + from spanner_orm import model | ||
| 19 | + from spanner_orm import relationship | ||
| 20 | + | ||
| 21 | + # pylint: disable=invalid-name | ||
| 22 | + Model = model.Model | ||
| 23 | + ModelRelationship = relationship.ModelRelationship | ||
| 24 | + SpannerApi = api.SpannerApi | ||
| 25 | + | ||
| 26 | + equal_to = condition.equal_to | ||
| 27 | + greater_than = condition.greater_than | ||
| 28 | + greater_than_or_equal_to = condition.greater_than_or_equal_to | ||
| 29 | + includes = condition.includes | ||
| 30 | + in_list = condition.in_list | ||
| 31 | + less_than = condition.less_than | ||
| 32 | + less_than_or_equal_to = condition.less_than_or_equal_to | ||
| 33 | + limit = condition.limit | ||
| 34 | + not_equal_to = condition.not_equal_to | ||
| 35 | + not_greater_than = condition.not_greater_than | ||
| 36 | + not_in_list = condition.not_in_list | ||
| 37 | + not_less_than = condition.not_less_than | ||
| 38 | + order_by = condition.order_by | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,12 +14,12 @@ | |||
| 14 | 14 | # limitations under the License. | |
| 15 | 15 | """Interacts with the Spanner database to read and manage table schemas.""" | |
| 16 | 16 | ||
| 17 | - from spanner_orm.api import TableReadApi | ||
| 17 | + from spanner_orm import api | ||
| 18 | 18 | ||
| 19 | 19 | from google.cloud import spanner | |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | - class DatabaseAdminApi(TableReadApi): | ||
| 22 | + class SpannerAdminApi(api.TableReadApi): | ||
| 23 | 23 | """Manages table schema information on Spanner.""" | |
| 24 | 24 | ||
| 25 | 25 | _connection = None | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,47 +15,43 @@ | |||
| 15 | 15 | """Retrieves database metadata.""" | |
| 16 | 16 | ||
| 17 | 17 | from collections import defaultdict | |
| 18 | - from spanner_orm.admin.api import DatabaseAdminApi | ||
| 19 | - from spanner_orm.condition import EqualityCondition | ||
| 20 | - from spanner_orm.condition import InequalityCondition | ||
| 21 | - from spanner_orm.condition import OrderByCondition | ||
| 22 | - from spanner_orm.condition import OrderType | ||
| 23 | - from spanner_orm.model import Model | ||
| 24 | - from spanner_orm.schemas.column import ColumnSchema | ||
| 25 | - from spanner_orm.schemas.index import IndexSchema | ||
| 26 | - from spanner_orm.schemas.index_column import IndexColumnSchema | ||
| 27 | - from spanner_orm.update import ColumnUpdate | ||
| 28 | - from spanner_orm.update import CreateTableUpdate | ||
| 29 | - from spanner_orm.update import IndexUpdate | ||
| 18 | + | ||
| 19 | + from spanner_orm import condition | ||
| 20 | + from spanner_orm import model | ||
| 21 | + from spanner_orm import update | ||
| 22 | + from spanner_orm.admin import api | ||
| 23 | + from spanner_orm.schemas import column | ||
| 24 | + from spanner_orm.schemas import index | ||
| 25 | + from spanner_orm.schemas import index_column | ||
| 30 | 26 | ||
| 31 | 27 | ||
| 32 | 28 | class DatabaseMetadata(object): | |
| 33 | 29 | """Retrieve table metadata from Spanner and returns it in a usable format.""" | |
| 34 | 30 | ||
| 35 | 31 | @classmethod | |
| 36 | 32 | def column_update(cls, schema_change): | |
| 37 | - assert isinstance(schema_change, ColumnUpdate) | ||
| 38 | - model = cls.models()[schema_change.table()] | ||
| 39 | - schema_change.validate(model) | ||
| 33 | + assert isinstance(schema_change, update.ColumnUpdate) | ||
| 34 | + klass = cls.models()[schema_change.table()] | ||
| 35 | + schema_change.validate(klass) | ||
| 40 | 36 | ||
| 41 | - DatabaseAdminApi.update_schema(schema_change.ddl(model)) | ||
| 37 | + api.SpannerAdminApi.update_schema(schema_change.ddl(klass)) | ||
| 42 | 38 | ||
| 43 | 39 | @classmethod | |
| 44 | 40 | def create_table(cls, schema_change): | |
| 45 | - assert isinstance(schema_change, CreateTableUpdate) | ||
| 41 | + assert isinstance(schema_change, update.CreateTableUpdate) | ||
| 46 | 42 | all_models = cls.models() | |
| 47 | 43 | assert schema_change.table() not in all_models | |
| 48 | 44 | schema_change.validate() | |
| 49 | 45 | ||
| 50 | - DatabaseAdminApi.update_schema(schema_change.ddl()) | ||
| 46 | + api.SpannerAdminApi.update_schema(schema_change.ddl()) | ||
| 51 | 47 | ||
| 52 | 48 | @classmethod | |
| 53 | 49 | def index_update(cls, schema_change): | |
| 54 | - assert isinstance(schema_change, IndexUpdate) | ||
| 55 | - model = cls.models()[schema_change.table()] | ||
| 56 | - schema_change.validate(model) | ||
| 50 | + assert isinstance(schema_change, update.IndexUpdate) | ||
| 51 | + klass = cls.models()[schema_change.table()] | ||
| 52 | + schema_change.validate(klass) | ||
| 57 | 53 | ||
| 58 | - DatabaseAdminApi.update_schema(schema_change.ddl(model)) | ||
| 54 | + api.SpannerAdminApi.update_schema(schema_change.ddl(klass)) | ||
| 59 | 55 | ||
| 60 | 56 | @classmethod | |
| 61 | 57 | def models(cls, transaction=None): | |
@@ -73,7 +69,7 @@ def make_classmethod(retval): | |||
| 73 | 69 | for table_name, schema in tables.items(): | |
| 74 | 70 | primary_index = indexes[table_name]['PRIMARY_KEY']['columns'] | |
| 75 | 71 | klass = type( | |
| 76 | - 'Model_{}'.format(table_name), (Model,), { | ||
| 72 | + 'Model_{}'.format(table_name), (model.Model,), { | ||
| 77 | 73 | 'primary_index_keys': make_method(primary_index), | |
| 78 | 74 | 'schema': make_classmethod(schema), | |
| 79 | 75 | 'table': make_classmethod(table_name) | |
@@ -85,9 +81,9 @@ def make_classmethod(retval): | |||
| 85 | 81 | def _tables(cls, transaction=None): | |
| 86 | 82 | """Compiles table information from column schema.""" | |
| 87 | 83 | tables = defaultdict(dict) | |
| 88 | - schemas = ColumnSchema.where(transaction, | ||
| 89 | - EqualityCondition('table_catalog', ''), | ||
| 90 | - EqualityCondition('table_schema', '')) | ||
| 84 | + schemas = column.ColumnSchema.where( | ||
| 85 | + transaction, condition.EqualityCondition('table_catalog', ''), | ||
| 86 | + condition.EqualityCondition('table_schema', '')) | ||
| 91 | 87 | for schema in schemas: | |
| 92 | 88 | tables[schema.table_name][schema.column_name] = schema.type() | |
| 93 | 89 | return tables | |
@@ -99,20 +95,21 @@ def _indexes(cls, transaction=None): | |||
| 99 | 95 | # Results are ordered by that so the index columns are added in the correct | |
| 100 | 96 | # order. None indicates that the key isn't really a part of the index, so we | |
| 101 | 97 | # skip those | |
| 102 | - index_column_schemas = IndexColumnSchema.where( | ||
| 103 | - transaction, EqualityCondition('table_catalog', ''), | ||
| 104 | - EqualityCondition('table_schema', ''), | ||
| 105 | - InequalityCondition('ordinal_position', None), | ||
| 106 | - OrderByCondition(('ordinal_position', OrderType.ASC))) | ||
| 98 | + index_column_schemas = index_column.IndexColumnSchema.where( | ||
| 99 | + transaction, condition.EqualityCondition('table_catalog', ''), | ||
| 100 | + condition.EqualityCondition('table_schema', ''), | ||
| 101 | + condition.InequalityCondition('ordinal_position', None), | ||
| 102 | + condition.OrderByCondition(('ordinal_position', | ||
| 103 | + condition.OrderType.ASC))) | ||
| 107 | 104 | ||
| 108 | 105 | index_columns = defaultdict(list) | |
| 109 | 106 | for schema in index_column_schemas: | |
| 110 | 107 | key = (schema.table_name, schema.index_name) | |
| 111 | 108 | index_columns[key].append(schema.column_name) | |
| 112 | 109 | ||
| 113 | - index_schemas = IndexSchema.where(transaction, | ||
| 114 | - EqualityCondition('table_catalog', ''), | ||
| 115 | - EqualityCondition('table_schema', '')) | ||
| 110 | + index_schemas = index.IndexSchema.where( | ||
| 111 | + transaction, condition.EqualityCondition('table_catalog', ''), | ||
| 112 | + condition.EqualityCondition('table_schema', '')) | ||
| 116 | 113 | indexes = defaultdict(dict) | |
| 117 | 114 | for schema in index_schemas: | |
| 118 | 115 | indexes[schema.table_name][schema.index_name] = { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -14,23 +14,22 @@ | |||
| 14 | 14 | # limitations under the License. | |
| 15 | 15 | """Class that interacts with spanner database.""" | |
| 16 | 16 | ||
| 17 | - from abc import ABC | ||
| 18 | - from abc import abstractmethod | ||
| 17 | + import abc | ||
| 19 | 18 | from google.cloud import spanner | |
| 20 | 19 | ||
| 21 | 20 | ||
| 22 | - class TableReadApi(ABC): | ||
| 23 | - """Handles read from table interactions with Spanner""" | ||
| 21 | + class SpannerReadApi(abc.ABC): | ||
| 22 | + """Handles sending read requests to Spanner""" | ||
| 24 | 23 | ||
| 25 | 24 | @classmethod | |
| 26 | - @abstractmethod | ||
| 27 | - def _database_connection(cls): | ||
| 25 | + @abc.abstractmethod | ||
| 26 | + def _connection(cls): | ||
| 28 | 27 | raise NotImplementedError | |
| 29 | 28 | ||
| 30 | 29 | @classmethod | |
| 31 | 30 | def run_read_only(cls, method, *args, **kwargs): | |
| 32 | - """Executes the provided callback method for read-only queries.""" | ||
| 33 | - with cls._database_connection().snapshot() as snapshot: | ||
| 31 | + """Wraps read-only queries in a read transaction.""" | ||
| 32 | + with cls._connection().snapshot() as snapshot: | ||
| 34 | 33 | return method(snapshot, *args, **kwargs) | |
| 35 | 34 | ||
| 36 | 35 | # Read methods | |
@@ -49,18 +48,18 @@ def sql_query(transaction, query, parameters, parameter_types): | |||
| 49 | 48 | return list(stream_results) | |
| 50 | 49 | ||
| 51 | 50 | ||
| 52 | - class TableWriteApi(ABC): | ||
| 53 | - """Handles write to table interactions with Spanner.""" | ||
| 51 | + class SpannerWriteApi(abc.ABC): | ||
| 52 | + """Handles sending write requests to Spanner.""" | ||
| 54 | 53 | ||
| 55 | 54 | @classmethod | |
| 56 | - @abstractmethod | ||
| 57 | - def _database_connection(cls): | ||
| 55 | + @abc.abstractmethod | ||
| 56 | + def _connection(cls): | ||
| 58 | 57 | raise NotImplementedError | |
| 59 | 58 | ||
| 60 | 59 | @classmethod | |
| 61 | 60 | def run_write(cls, *args, **kwargs): | |
| 62 | - """Executes the provided callback method in a transaction.""" | ||
| 63 | - return cls._database_connection().run_in_transaction(*args, **kwargs) | ||
| 61 | + """Wraps write and read-write queries in a transaction.""" | ||
| 62 | + return cls._connection().run_in_transaction(*args, **kwargs) | ||
| 64 | 63 | ||
| 65 | 64 | # Write methods | |
| 66 | 65 | @staticmethod | |
@@ -75,25 +74,25 @@ def update(transaction, table_name, columns, values): | |||
| 75 | 74 | ||
| 76 | 75 | @staticmethod | |
| 77 | 76 | def upsert(transaction, table_name, columns, values): | |
| 78 | - """Updates row if primary key already exists, otherwise, creates a row.""" | ||
| 77 | + """Updates existing rows of a table or adds rows if they don't exist.""" | ||
| 79 | 78 | transaction.insert_or_update( | |
| 80 | 79 | table=table_name, columns=columns, values=values) | |
| 81 | 80 | ||
| 82 | 81 | ||
| 83 | - class DatabaseApi(TableReadApi, TableWriteApi): | ||
| 82 | + class SpannerApi(SpannerReadApi, SpannerWriteApi): | ||
| 84 | 83 | """Class that handles reading from and writing to Spanner tables.""" | |
| 85 | 84 | ||
| 86 | - _connection = None | ||
| 85 | + _spanner_connection = None | ||
| 87 | 86 | _connection_info = None | |
| 88 | 87 | ||
| 89 | 88 | @classmethod | |
| 90 | - def _database_connection(cls): | ||
| 91 | - assert cls._connection is not None | ||
| 92 | - return cls._connection | ||
| 89 | + def _connection(cls): | ||
| 90 | + assert cls._spanner_connection is not None, 'Not connected to Spanner' | ||
| 91 | + return cls._spanner_connection | ||
| 93 | 92 | ||
| 94 | 93 | # Spanner connection methods | |
| 95 | 94 | @classmethod | |
| 96 | - def connect(cls, project, instance, database): | ||
| 95 | + def connect(cls, *, project, instance, database): | ||
| 97 | 96 | """Connects to the specified Spanner database.""" | |
| 98 | 97 | connection_info = (project, instance, database) | |
| 99 | 98 | if cls._connection is not None: | |
| Back | FazBrowse Home | New Git URL |
0 commit comments