DefPixel 0.1.0__3-py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. DefPixel/DataAccessObject/Configuration.py +15 -0
  2. DefPixel/DataAccessObject/Connection.py +25 -0
  3. DefPixel/DataAccessObject/Implements/Sqlite/Configuration.py +16 -0
  4. DefPixel/DataAccessObject/Implements/Sqlite/Connection.py +96 -0
  5. DefPixel/DataAccessObject/Implements/Sqlite/Constraint.py +9 -0
  6. DefPixel/DataAccessObject/Implements/Sqlite/Constraints/ForeignKey.py +16 -0
  7. DefPixel/DataAccessObject/Implements/Sqlite/Constraints/PrimaryKey.py +15 -0
  8. DefPixel/DataAccessObject/Implements/Sqlite/Constraints/Unique.py +25 -0
  9. DefPixel/DataAccessObject/Implements/Sqlite/Constraints/__init__.py +11 -0
  10. DefPixel/DataAccessObject/Implements/Sqlite/Context.py +36 -0
  11. DefPixel/DataAccessObject/Implements/Sqlite/Cursor.py +87 -0
  12. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Create.py +115 -0
  13. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Delete.py +35 -0
  14. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Drop.py +34 -0
  15. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Get.py +24 -0
  16. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Insert.py +59 -0
  17. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Select.py +109 -0
  18. DefPixel/DataAccessObject/Implements/Sqlite/Executors/Update.py +34 -0
  19. DefPixel/DataAccessObject/Implements/Sqlite/Executors/__init__.py +19 -0
  20. DefPixel/DataAccessObject/Implements/Sqlite/Expr.py +42 -0
  21. DefPixel/DataAccessObject/Implements/Sqlite/Exprs/Alias.py +20 -0
  22. DefPixel/DataAccessObject/Implements/Sqlite/Exprs/Is.py +29 -0
  23. DefPixel/DataAccessObject/Implements/Sqlite/Exprs/__init__.py +13 -0
  24. DefPixel/DataAccessObject/Implements/Sqlite/Filters/Compare.py +149 -0
  25. DefPixel/DataAccessObject/Implements/Sqlite/Filters/Operator.py +26 -0
  26. DefPixel/DataAccessObject/Implements/Sqlite/Filters/String.py +23 -0
  27. DefPixel/DataAccessObject/Implements/Sqlite/Filters/__init__.py +30 -0
  28. DefPixel/DataAccessObject/Implements/Sqlite/Function.py +15 -0
  29. DefPixel/DataAccessObject/Implements/Sqlite/Functions/Common.py +34 -0
  30. DefPixel/DataAccessObject/Implements/Sqlite/Functions/Condition.py +21 -0
  31. DefPixel/DataAccessObject/Implements/Sqlite/Functions/__init__.py +16 -0
  32. DefPixel/DataAccessObject/Implements/Sqlite/Index.py +23 -0
  33. DefPixel/DataAccessObject/Implements/Sqlite/Joins/FullOuter.py +19 -0
  34. DefPixel/DataAccessObject/Implements/Sqlite/Joins/Inner.py +19 -0
  35. DefPixel/DataAccessObject/Implements/Sqlite/Joins/Join.py +31 -0
  36. DefPixel/DataAccessObject/Implements/Sqlite/Joins/LeftOuter.py +19 -0
  37. DefPixel/DataAccessObject/Implements/Sqlite/Joins/RightOuter.py +19 -0
  38. DefPixel/DataAccessObject/Implements/Sqlite/Joins/__init__.py +13 -0
  39. DefPixel/DataAccessObject/Implements/Sqlite/Mapping.py +303 -0
  40. DefPixel/DataAccessObject/Implements/Sqlite/Orders/Ascend.py +24 -0
  41. DefPixel/DataAccessObject/Implements/Sqlite/Orders/Descend.py +24 -0
  42. DefPixel/DataAccessObject/Implements/Sqlite/Orders/__init__.py +9 -0
  43. DefPixel/DataAccessObject/Implements/Sqlite/Session.py +37 -0
  44. DefPixel/DataAccessObject/Implements/Sqlite/Type.py +75 -0
  45. DefPixel/DataAccessObject/Implements/Sqlite/Types/Binary.py +28 -0
  46. DefPixel/DataAccessObject/Implements/Sqlite/Types/DateTime.py +42 -0
  47. DefPixel/DataAccessObject/Implements/Sqlite/Types/Numeric.py +49 -0
  48. DefPixel/DataAccessObject/Implements/Sqlite/Types/String.py +28 -0
  49. DefPixel/DataAccessObject/Implements/Sqlite/Types/__init__.py +34 -0
  50. DefPixel/DataAccessObject/Implements/Sqlite/__init__.py +39 -0
  51. DefPixel/DataAccessObject/Implements/__init__.py +1 -0
  52. DefPixel/DataAccessObject/Properties/Database/Context.py +33 -0
  53. DefPixel/DataAccessObject/Properties/Database/Cursor.py +27 -0
  54. DefPixel/DataAccessObject/Properties/Database/Database.py +48 -0
  55. DefPixel/DataAccessObject/Properties/Database/Executor.py +38 -0
  56. DefPixel/DataAccessObject/Properties/Database/Executors.py +31 -0
  57. DefPixel/DataAccessObject/Properties/Database/Fetch.py +37 -0
  58. DefPixel/DataAccessObject/Properties/Database/Filter.py +21 -0
  59. DefPixel/DataAccessObject/Properties/Database/Run.py +39 -0
  60. DefPixel/DataAccessObject/Properties/Database/Session.py +36 -0
  61. DefPixel/DataAccessObject/Properties/Database/__init__.py +25 -0
  62. DefPixel/DataAccessObject/Properties/Dataclass.py +25 -0
  63. DefPixel/DataAccessObject/Properties/Document/Document.py +36 -0
  64. DefPixel/DataAccessObject/Properties/Document/__init__.py +7 -0
  65. DefPixel/DataAccessObject/Properties/Index/Index.py +48 -0
  66. DefPixel/DataAccessObject/Properties/Index/__init__.py +7 -0
  67. DefPixel/DataAccessObject/Properties/KeyValue/KeyValue.py +44 -0
  68. DefPixel/DataAccessObject/Properties/KeyValue/__init__.py +7 -0
  69. DefPixel/DataAccessObject/Properties/__init__.py +15 -0
  70. DefPixel/DataAccessObject/__init__.py +9 -0
  71. DefPixel/Validator/Pattern.py +36 -0
  72. DefPixel/Validator/Patterns/Array.py +30 -0
  73. DefPixel/Validator/Patterns/Common.py +92 -0
  74. DefPixel/Validator/Patterns/Compare.py +180 -0
  75. DefPixel/Validator/Patterns/Condition.py +60 -0
  76. DefPixel/Validator/Patterns/DataObject.py +85 -0
  77. DefPixel/Validator/Patterns/DateTime.py +111 -0
  78. DefPixel/Validator/Patterns/Number.py +43 -0
  79. DefPixel/Validator/Patterns/Object.py +150 -0
  80. DefPixel/Validator/Patterns/Size.py +110 -0
  81. DefPixel/Validator/Patterns/String.py +85 -0
  82. DefPixel/Validator/Patterns/Type.py +350 -0
  83. DefPixel/Validator/Patterns/__init__.py +137 -0
  84. DefPixel/Validator/Validate.py +29 -0
  85. DefPixel/Validator/Validator.py +30 -0
  86. DefPixel/Validator/__init__.py +11 -0
  87. DefPixel/__init__.py +0 -0
  88. defpixel-0.1.0.dist-info/METADATA +114 -0
  89. defpixel-0.1.0.dist-info/RECORD +92 -0
  90. defpixel-0.1.0.dist-info/WHEEL +6 -0
  91. defpixel-0.1.0.dist-info/licenses/LICENSE +674 -0
  92. defpixel-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from abc import ABCMeta, abstractmethod
4
+
5
+ __all__ = (
6
+ 'Configuration'
7
+ )
8
+
9
+
10
+ class Configuration(metaclass=ABCMeta):
11
+ """Configuration Interface"""
12
+
13
+ @abstractmethod
14
+ def __init__(self, *args, **kwargs):
15
+ raise NotImplementedError('{} must be implemented __init__'.format(self.__class__.__name__))
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .Configuration import Configuration
4
+
5
+ from abc import ABCMeta, abstractmethod
6
+
7
+ __all__ = (
8
+ 'Connection'
9
+ )
10
+
11
+
12
+ class Connection(metaclass=ABCMeta):
13
+ """Connection Interface"""
14
+
15
+ @abstractmethod
16
+ def __init__(self, conf: Configuration):
17
+ raise NotImplementedError('{} must be implemented __init__ method'.format(self.__class__.__name__))
18
+
19
+ @abstractmethod
20
+ def connect(self):
21
+ raise NotImplementedError('{} must be implemented connect method'.format(self.__class__.__name__))
22
+
23
+ @abstractmethod
24
+ def close(self):
25
+ raise NotImplementedError('{} must be implemented close method'.format(self.__class__.__name__))
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject import Configuration as BaseConfiguration
4
+
5
+ __all__ = (
6
+ 'Configuration'
7
+ )
8
+
9
+
10
+ class Configuration(BaseConfiguration):
11
+ """Configuration Class for Sqlite"""
12
+
13
+ def __init__(self, path: str, autocommit: bool = False):
14
+ self.path = path
15
+ self.autocommit = autocommit
16
+ return
@@ -0,0 +1,96 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from sqlite3 import (
4
+ Row,
5
+ connect,
6
+ )
7
+ from DefPixel.DataAccessObject import Connection as BaseConnection
8
+ from DefPixel.DataAccessObject.Properties.Database import (
9
+ Database,
10
+ Run,
11
+ )
12
+ from .Cursor import Cursor
13
+ from .Session import Session
14
+
15
+ __all__ = (
16
+ 'Connection',
17
+ )
18
+
19
+
20
+ class Connection(BaseConnection, Database, Run):
21
+ """SQLite connection with explicit lifecycle and transaction management."""
22
+
23
+ def __init__(self, conf):
24
+ self.conf = conf
25
+ self.connection = None
26
+ return
27
+
28
+ def connect(self):
29
+ if self.connection is not None:
30
+ raise RuntimeError('The SQLite connection is already open')
31
+ self.connection = connect(
32
+ self.conf.path,
33
+ isolation_level=None if self.conf.autocommit else 'DEFERRED',
34
+ check_same_thread=False,
35
+ )
36
+ self.connection.row_factory = Row
37
+ return
38
+
39
+ def active(self):
40
+ if self.connection is None:
41
+ raise RuntimeError('The SQLite connection is not open')
42
+ return self.connection
43
+
44
+ def close(self):
45
+ if self.connection is not None:
46
+ self.connection.close()
47
+ self.connection = None
48
+ return
49
+
50
+ def begin(self):
51
+ self.active().execute('BEGIN')
52
+ return
53
+
54
+ def execute(
55
+ self,
56
+ sql,
57
+ *args,
58
+ ):
59
+ return self.cursor().execute(sql, *args)
60
+
61
+ def executes(
62
+ self,
63
+ sql,
64
+ *args,
65
+ ):
66
+ return self.cursor().executes(sql, *args)
67
+
68
+ def run(
69
+ self,
70
+ executor,
71
+ filter=None,
72
+ fetch=None,
73
+ ):
74
+ cursor = self.cursor()
75
+ try:
76
+ return cursor.run(
77
+ executor,
78
+ filter=filter,
79
+ fetch=fetch,
80
+ )
81
+ finally:
82
+ cursor.close()
83
+
84
+ def cursor(self):
85
+ return Cursor(self.active().cursor())
86
+
87
+ def session(self):
88
+ return Session(self.active())
89
+
90
+ def commit(self):
91
+ self.active().commit()
92
+ return
93
+
94
+ def rollback(self):
95
+ self.active().rollback()
96
+ return
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ __all__ = (
4
+ 'Constraint'
5
+ )
6
+
7
+
8
+ class Constraint:
9
+ """Base marker for SQLite constraint declarations."""
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Constraint import Constraint
4
+
5
+ __all__ = (
6
+ 'ForeignKey'
7
+ )
8
+
9
+
10
+ class ForeignKey(Constraint):
11
+ def __init__(self, cols, reference, referenceCols):
12
+ self.cols = cols if isinstance(cols, (tuple, list)) else [cols]
13
+ self.reference = reference
14
+ self.referenceCols = referenceCols if isinstance(referenceCols, (tuple, list)) else [referenceCols]
15
+ return
16
+
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Constraint import Constraint
4
+
5
+ __all__ = (
6
+ 'PrimaryKey'
7
+ )
8
+
9
+
10
+ class PrimaryKey(Constraint):
11
+ def __init__(self, cols, autoincrement=False):
12
+ self.cols = cols if isinstance(cols, (tuple, list)) else [cols]
13
+ self.autoincrement = autoincrement
14
+ return
15
+
@@ -0,0 +1,25 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from ..Constraint import Constraint
4
+
5
+ from typing import Union, Sequence
6
+
7
+ __all__ = (
8
+ 'Unique'
9
+ )
10
+
11
+
12
+ class Unique(Constraint):
13
+ def __init__(
14
+ self,
15
+ name: str,
16
+ colexprs: Union[str, Sequence[str]],
17
+ expr: str = None,
18
+ notexists: bool = None,
19
+ ):
20
+ self.name = name
21
+ self.colexprs = colexprs if isinstance(colexprs, (tuple, list)) else [colexprs]
22
+ self.expr = expr
23
+ self.notexists = notexists
24
+ return
25
+
@@ -0,0 +1,11 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .PrimaryKey import PrimaryKey
4
+ from .ForeignKey import ForeignKey
5
+ from .Unique import Unique
6
+
7
+ __all__ = (
8
+ 'PrimaryKey',
9
+ 'ForeignKey',
10
+ 'Unique',
11
+ )
@@ -0,0 +1,36 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import Context as BaseContext
4
+
5
+ __all__ = (
6
+ 'Context',
7
+ )
8
+
9
+
10
+ class Context(BaseContext):
11
+ """Context exposing SQLite execution results."""
12
+
13
+ def __init__(
14
+ self,
15
+ cursor,
16
+ query=None,
17
+ ):
18
+ self.cursor = cursor
19
+ self.statement = query
20
+ return
21
+
22
+ def rows(self):
23
+ return [dict(row) for row in self.cursor.fetchall()]
24
+
25
+ def row(self):
26
+ row = self.cursor.fetchone()
27
+ return dict(row) if row is not None else None
28
+
29
+ def count(self):
30
+ return self.cursor.connection.total_changes
31
+
32
+ @property
33
+ def query(self):
34
+ if self.statement is None:
35
+ raise RuntimeError('The executed query is not available in this context')
36
+ return self.statement
@@ -0,0 +1,87 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import (
4
+ Cursor as BaseCursor,
5
+ Executor,
6
+ Executors,
7
+ Fetch,
8
+ Run,
9
+ )
10
+ from .Context import Context
11
+ from .Mapping import inspect_model
12
+
13
+ __all__ = (
14
+ 'Cursor',
15
+ )
16
+
17
+
18
+ class Cursor(BaseCursor, Run):
19
+ """SQLite cursor supporting direct SQL and ORM execution."""
20
+
21
+ def __init__(self, cursor):
22
+ self.cursor = cursor
23
+ return
24
+
25
+ def execute(
26
+ self,
27
+ sql,
28
+ *args,
29
+ ):
30
+ self.cursor.execute(sql, args)
31
+ return Context(self.cursor, sql)
32
+
33
+ def executes(
34
+ self,
35
+ sql,
36
+ *args,
37
+ ):
38
+ self.cursor.executemany(sql, args)
39
+ return Context(self.cursor, sql)
40
+
41
+ def run(
42
+ self,
43
+ executor,
44
+ filter=None,
45
+ fetch=None,
46
+ ):
47
+ if fetch is not None:
48
+ inspect_model(fetch)
49
+ if isinstance(executor, Executor):
50
+ self.cursor.execute(executor.query, executor.args)
51
+ if isinstance(executor, Fetch):
52
+ return executor.fetch(
53
+ self,
54
+ filter=filter,
55
+ fetch=fetch,
56
+ )
57
+ return None
58
+ if isinstance(executor, Executors):
59
+ result = []
60
+ for statement in executor:
61
+ if not isinstance(statement, Executor):
62
+ raise TypeError('Executors must yield Executor objects')
63
+ value = self.run(
64
+ statement,
65
+ filter=filter,
66
+ fetch=fetch,
67
+ )
68
+ if isinstance(value, list):
69
+ result.extend(value)
70
+ elif value is not None:
71
+ result.append(value)
72
+ return result
73
+ raise TypeError('run requires an Executor or Executors object')
74
+
75
+ def rows(self):
76
+ return [dict(row) for row in self.cursor.fetchall()]
77
+
78
+ def row(self):
79
+ row = self.cursor.fetchone()
80
+ return dict(row) if row is not None else None
81
+
82
+ def count(self):
83
+ raise RuntimeError('SQLite query result row counts are not supported')
84
+
85
+ def close(self):
86
+ self.cursor.close()
87
+ return
@@ -0,0 +1,115 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from dataclasses import MISSING
4
+ from DefPixel.DataAccessObject.Properties.Database import Executors
5
+ from ..Constraints import (
6
+ ForeignKey,
7
+ PrimaryKey,
8
+ Unique,
9
+ )
10
+ from ..Function import Function
11
+ from ..Index import Index
12
+ from ..Mapping import (
13
+ Statement,
14
+ identifier,
15
+ inspect_model,
16
+ )
17
+ from ..Expr import Expr
18
+
19
+ __all__ = (
20
+ 'Create',
21
+ )
22
+
23
+
24
+ class Create(Executors):
25
+ """Provide table, view, and index creation as individual execution statements."""
26
+
27
+ def __init__(
28
+ self,
29
+ o,
30
+ notexist=True,
31
+ ):
32
+ mapping = inspect_model(o)
33
+ self.executors = []
34
+ if mapping.kind == 'view':
35
+ self.executors.append(Statement(
36
+ 'CREATE VIEW {}{} AS {}'.format(
37
+ 'IF NOT EXISTS ' if notexist else '',
38
+ identifier(mapping.name),
39
+ mapping.executor.query,
40
+ ),
41
+ ))
42
+ return
43
+ def column_name(name):
44
+ if name in mapping.columns:
45
+ return identifier(mapping.columns[name].key)
46
+ if name in {spec.key for spec in mapping.columns.values()}:
47
+ return identifier(name)
48
+ raise ValueError('Constraint column is not mapped: {}'.format(name))
49
+ keys = [item for item in mapping.constraints if isinstance(item, PrimaryKey)]
50
+ if len(keys) > 1:
51
+ raise ValueError('Multiple primary key definitions are not allowed')
52
+ auto = keys[0] if keys and keys[0].autoincrement else None
53
+ if auto is not None and len(auto.cols) != 1:
54
+ raise ValueError('AUTOINCREMENT requires a single INTEGER primary key')
55
+ definitions = []
56
+ for spec in mapping.columns.values():
57
+ definition = '{} {}'.format(identifier(spec.key), spec.typestr)
58
+ if auto is not None and column_name(auto.cols[0]) == identifier(spec.key):
59
+ if spec.typestr != 'INTEGER':
60
+ raise ValueError('AUTOINCREMENT requires an INTEGER column')
61
+ definition += ' PRIMARY KEY AUTOINCREMENT'
62
+ if not spec.null:
63
+ definition += ' NOT NULL'
64
+ if spec.coldef is not MISSING:
65
+ value = spec.coldef
66
+ if isinstance(value, Function):
67
+ definition += ' DEFAULT ({})'.format(value)
68
+ else:
69
+ definition += ' DEFAULT {}'.format(Expr.literal(spec.encode(value)))
70
+ definitions.append(definition)
71
+ for constraint in mapping.constraints:
72
+ if isinstance(constraint, PrimaryKey):
73
+ if auto is None:
74
+ definitions.append('PRIMARY KEY({})'.format(
75
+ ', '.join(column_name(name) for name in constraint.cols),
76
+ ))
77
+ elif isinstance(constraint, ForeignKey):
78
+ if len(constraint.cols) != len(constraint.referenceCols):
79
+ raise ValueError('Foreign key column counts do not match')
80
+ definitions.append('FOREIGN KEY({}) REFERENCES {}({})'.format(
81
+ ', '.join(column_name(name) for name in constraint.cols),
82
+ identifier(constraint.reference),
83
+ ', '.join(identifier(name) for name in constraint.referenceCols),
84
+ ))
85
+ elif not isinstance(constraint, Unique):
86
+ raise TypeError('Unsupported SQLite constraint')
87
+ self.executors.append(Statement(
88
+ 'CREATE TABLE {}{}({})'.format(
89
+ 'IF NOT EXISTS ' if notexist else '',
90
+ identifier(mapping.name),
91
+ ', '.join(definitions),
92
+ ),
93
+ ))
94
+ for index in tuple(
95
+ value for value in mapping.constraints if isinstance(value, Unique)
96
+ ) + mapping.indexes:
97
+ if not isinstance(index, (Index, Unique)):
98
+ raise TypeError('Unsupported SQLite index')
99
+ self.executors.append(Statement(
100
+ 'CREATE {}INDEX {}{} ON {}({}){}'.format(
101
+ 'UNIQUE ' if isinstance(index, Unique) else '',
102
+ 'IF NOT EXISTS ' if index.notexists else '',
103
+ identifier(index.name),
104
+ identifier(mapping.name),
105
+ ', '.join(
106
+ column_name(value) if isinstance(value, str) else str(value)
107
+ for value in index.colexprs
108
+ ),
109
+ ' WHERE {}'.format(index.expr) if index.expr else '',
110
+ ),
111
+ ))
112
+ return
113
+
114
+ def __iter__(self):
115
+ return iter(self.executors)
@@ -0,0 +1,35 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import Executor
4
+ from ..Mapping import (
5
+ identifier,
6
+ inspect_model,
7
+ )
8
+
9
+ __all__ = (
10
+ 'Delete',
11
+ )
12
+
13
+
14
+ class Delete(Executor):
15
+ """Delete query using an explicit table mapping."""
16
+
17
+ def __init__(self, o):
18
+ self.mapping = inspect_model(o, 'table')
19
+ self.conds = ()
20
+ return
21
+
22
+ def where(self, *args):
23
+ self.conds = args
24
+ return self
25
+
26
+ @property
27
+ def query(self):
28
+ return 'DELETE FROM {}{}'.format(
29
+ identifier(self.mapping.name),
30
+ ' WHERE ' + ' AND '.join(str(cond) for cond in self.conds) if self.conds else '',
31
+ )
32
+
33
+ @property
34
+ def args(self):
35
+ return ()
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import Executors
4
+ from ..Mapping import (
5
+ Statement,
6
+ identifier,
7
+ inspect_model,
8
+ )
9
+
10
+ __all__ = (
11
+ 'Drop',
12
+ )
13
+
14
+
15
+ class Drop(Executors):
16
+ """SQLite drops associated indexes when a table is dropped."""
17
+
18
+ def __init__(
19
+ self,
20
+ o,
21
+ exist=True,
22
+ ):
23
+ mapping = inspect_model(o)
24
+ self.executors = [Statement(
25
+ 'DROP {} {}{}'.format(
26
+ mapping.kind.upper(),
27
+ 'IF EXISTS ' if exist else '',
28
+ identifier(mapping.name),
29
+ ),
30
+ )]
31
+ return
32
+
33
+ def __iter__(self):
34
+ return iter(self.executors)
@@ -0,0 +1,24 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from .Select import Select
4
+
5
+ __all__ = (
6
+ 'Get',
7
+ )
8
+
9
+
10
+ class Get(Select):
11
+ """Return the first result while preserving the existing Get interface."""
12
+
13
+ def fetch(
14
+ self,
15
+ cursor,
16
+ filter=None,
17
+ fetch=None,
18
+ ):
19
+ rows = super().fetch(
20
+ cursor,
21
+ filter=filter,
22
+ fetch=fetch,
23
+ )
24
+ return rows[0] if rows else None
@@ -0,0 +1,59 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from DefPixel.DataAccessObject.Properties.Database import (
4
+ Executor,
5
+ Fetch,
6
+ )
7
+ from ..Mapping import (
8
+ identifier,
9
+ inspect_model,
10
+ )
11
+
12
+ __all__ = (
13
+ 'Insert',
14
+ )
15
+
16
+
17
+ class Insert(Executor, Fetch):
18
+ """Map field names to columns and bind validated values."""
19
+
20
+ def __init__(self, o):
21
+ self.mapping = inspect_model(o, 'table')
22
+ self.kwargs = {}
23
+ return
24
+
25
+ def values(self, **kwargs):
26
+ self.kwargs.update(self.mapping.values(kwargs))
27
+ return self
28
+
29
+ @property
30
+ def query(self):
31
+ if not self.kwargs:
32
+ return 'INSERT INTO {} DEFAULT VALUES RETURNING *'.format(
33
+ identifier(self.mapping.name),
34
+ )
35
+ return 'INSERT INTO {}({}) VALUES({}) RETURNING *'.format(
36
+ identifier(self.mapping.name),
37
+ ', '.join(identifier(key) for key in self.kwargs),
38
+ ', '.join(['?'] * len(self.kwargs)),
39
+ )
40
+
41
+ @property
42
+ def args(self):
43
+ return tuple(self.kwargs.values())
44
+
45
+ def fetch(
46
+ self,
47
+ cursor,
48
+ filter=None,
49
+ fetch=None,
50
+ ):
51
+ rows = cursor.rows()
52
+ if not rows:
53
+ return None
54
+ row = rows[0]
55
+ if filter is not None:
56
+ row = filter(row)
57
+ if fetch is not None:
58
+ return inspect_model(fetch).restore(row)
59
+ return row