CRUD Classes

Sync CRUD

Bases: BaseCrud, Generic[M]

Abstracts CRUD actions for model associated tables

Source code in ardilla/crud.py
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
class Crud(BaseCrud, Generic[M]):
    """Abstracts CRUD actions for model associated tables"""

    connection: sqlite3.Connection

    def _do_insert(
        self,
        ignore: bool = False,
        returning: bool = True,
        /,
        **kws: SQLFieldType,
    ) -> Optional[M]:
        """private helper method for insertion methods

        Args:
            ignore (bool, optional): Ignores conflicts silently. Defaults to False.
            returning (bool, optional): Determines if the query should return the inserted row. Defaults to True.
            kws (SQLFieldType): the column name and values for the insert query

        Raises:
            QueryExecutionError: when sqlite3.IntegrityError happens because of a conflic

        Returns:
            An instance of model if any row is returned
        """
        q, vals = queries.for_do_insert(self.tablename, ignore, returning, kws)

        with contextcursor(self.connection) as cur:
            try:
                cur.execute(q, vals)
            except sqlite3.IntegrityError as e:
                raise QueryExecutionError(str(e))

            row = cur.fetchone()
            self.connection.commit()
            if returning and row:
                return self._row2obj(row, cur.lastrowid)

        return None

    def insert(self, **kws: SQLFieldType) -> M:
        """Inserts a record into the database.

        Args:
            kws (SQLFieldType): The keyword arguments are passed as the column names and values
                to the insert query

        Returns:
            Creates a new entry in the database and returns the object

        Rises:
            `ardilla.error.QueryExecutionError`: if there's a conflict when inserting the record
        """
        self.verify_kws(kws)
        return self._do_insert(False, True, **kws)

    def insert_or_ignore(self, **kws: SQLFieldType) -> Optional[M]:
        """Inserts a record to the database with the keywords passed. It ignores conflicts.

        Args:
            kws (SQLFieldType): The keyword arguments are passed as the column names and values
                to the insert query

        Returns:
            The newly created row as an instance of the model if there was no conflicts
        """
        self.verify_kws(kws)
        return self._do_insert(True, True, **kws)

    def get_or_none(self, **kws: SQLFieldType) -> Optional[M]:
        """Returns a row as an instance of the model if one is found or none

        Args:
            kws (SQLFieldType): The keyword arguments are passed as column names and values to
                a select query

        Example:
            ```py
            crud.get_or_none(id=42)

            # returns an object with id of 42 or None if there isn't one in the database
            ```

        Returns:
            The object found with the criteria if any
        """
        self.verify_kws(kws)
        q, vals = queries.for_get_or_none(self.tablename, kws)
        with contextcursor(self.connection) as cur:
            cur.execute(q, vals)
            row: Union[Row, None] = cur.fetchone()
            if row:
                return self._row2obj(row)
        return None

    def get_or_create(self, **kws: SQLFieldType) -> tuple[M, bool]:
        """Returns an object from the database with the spefied matching data
        Args:
            kws (SQLFieldType): the key value pairs will be used to query for an existing row
                if no record is found then a new row will be inserted
        Returns:
            A tuple with two values, the object and a boolean indicating if the
                object was newly created or not
        """
        self.verify_kws(kws)
        created = False
        result = self.get_or_none(**kws)
        if not result:
            result = self.insert_or_ignore(**kws)
            created = True
        return result, created

    def get_all(self) -> list[M]:
        """Gets all objects from the database
        Returns:
            A list with all the rows in table as instances of the model
        """
        return self.get_many()

    def get_many(
        self,
        order_by: Optional[dict[str, str]] = None,
        limit: Optional[int] = None,
        **kws: SQLFieldType,
    ) -> list[M]:
        """Queries the database and returns objects that meet the criteris

        Args:
            order_by (Optional[dict[str, str]], optional): An ordering dict. Defaults to None.
                The ordering should have the structure: `{'column_name': 'ASC' OR 'DESC'}`
                Case in values is insensitive

            limit (Optional[int], optional): The number of items to return. Defaults to None.
            kws (SQLFieldType): The column names and values for the select query

        Returns:
            a list of rows matching the criteria as intences of the model
        """
        self.verify_kws(kws)
        q, vals = queries.for_get_many(
            self.Model, 
            order_by=order_by,
            limit=limit, 
            kws=kws,
        )
        with contextcursor(self.connection) as cur:
            cur.execute(q, vals)
            rows: list[Row] = cur.fetchall()
            return [self._row2obj(row) for row in rows]

    def save_one(self, obj: M) -> Literal[True]:
        """Saves one object to the database

        Args:
            obj (M): the object to persist

        Returns:
            The literal `True` if the method ran successfuly
        """
        q, vals = queries.for_save_one(obj)
        try:
            self.connection.execute(q, vals)
            self.connection.commit()
        except:
            raise disconnected_engine_error
        return True

    def save_many(self, *objs: tuple[M]) -> Literal[True]:
        """Saves all the passed objects to the database

        Args:
            objs (M): the objects to persist

        Returns:
            The literal `True` if the method ran successfuly
        """
        q, vals = queries.for_save_many(objs)
        try:
            self.connection.executemany(q, vals)
            self.connection.commit()
        except:
            raise disconnected_engine_error

        return True

    def delete_one(self, obj: M) -> Literal[True]:
        """
        Deletes the object from the database (won't delete the actual object)
        If the object has a PK field or the rowid setup, those will be
        used to locate the obj and delete it.
        If not, this function will delete any row that meets the values of the object


        Args:
            obj (M): the object to delete

        Returns:
            The literal `True` if the method ran successfuly

        """

        q, vals = queries.for_delete_one(obj)
        try:
            self.connection.execute(q, vals)
            self.connection.commit()
        except:
            raise disconnected_engine_error
        return True

    def delete_many(self, *objs: M) -> Literal[True]:
        """
        Deletes all the objects passed

        Args:
            objs (M): the object to delete

        Returns:
            The literal `True` if the method ran successfuly

        """
        q, vals = queries.for_delete_many(objs)
        try:
            self.connection.execute(q, vals)
            self.connection.commit()
        except:
            raise disconnected_engine_error
        return True

    def count(self, column: str = '*',/, **kws) -> int:
        """Returns an integer of the number of non null values in a column
        Or the total number of rows if '*' is passed

        Args:
            column (str, optional): The column name to count rows on. 
                Defaults to '*' which counts all the rows in the table

        Returns:
            int: the number of rows with non null values in a column or the number of rows in a table
        """
        self.verify_kws(kws)

        tablename = self.Model.__tablename__
        if column not in self.Model.__fields__ and column != '*':
            raise BadQueryError(f'"{column}" is not a field of the "{tablename}" table')


        q, vals = queries.for_count(tablename, column, kws)
        with contextcursor(self.connection) as cur:
            cur.execute(q, vals)
            row = cur.fetchone()

            count = row['total_count']

        return count

count(column='*', /, **kws)

Returns an integer of the number of non null values in a column Or the total number of rows if '*' is passed

Parameters:

Name Type Description Default
column str

The column name to count rows on. Defaults to '*' which counts all the rows in the table

'*'

Returns:

Name Type Description
int int

the number of rows with non null values in a column or the number of rows in a table

Source code in ardilla/crud.py
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
def count(self, column: str = '*',/, **kws) -> int:
    """Returns an integer of the number of non null values in a column
    Or the total number of rows if '*' is passed

    Args:
        column (str, optional): The column name to count rows on. 
            Defaults to '*' which counts all the rows in the table

    Returns:
        int: the number of rows with non null values in a column or the number of rows in a table
    """
    self.verify_kws(kws)

    tablename = self.Model.__tablename__
    if column not in self.Model.__fields__ and column != '*':
        raise BadQueryError(f'"{column}" is not a field of the "{tablename}" table')


    q, vals = queries.for_count(tablename, column, kws)
    with contextcursor(self.connection) as cur:
        cur.execute(q, vals)
        row = cur.fetchone()

        count = row['total_count']

    return count

delete_many(*objs)

Deletes all the objects passed

Parameters:

Name Type Description Default
objs M

the object to delete

()

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/crud.py
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
def delete_many(self, *objs: M) -> Literal[True]:
    """
    Deletes all the objects passed

    Args:
        objs (M): the object to delete

    Returns:
        The literal `True` if the method ran successfuly

    """
    q, vals = queries.for_delete_many(objs)
    try:
        self.connection.execute(q, vals)
        self.connection.commit()
    except:
        raise disconnected_engine_error
    return True

delete_one(obj)

Deletes the object from the database (won't delete the actual object) If the object has a PK field or the rowid setup, those will be used to locate the obj and delete it. If not, this function will delete any row that meets the values of the object

Parameters:

Name Type Description Default
obj M

the object to delete

required

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/crud.py
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
def delete_one(self, obj: M) -> Literal[True]:
    """
    Deletes the object from the database (won't delete the actual object)
    If the object has a PK field or the rowid setup, those will be
    used to locate the obj and delete it.
    If not, this function will delete any row that meets the values of the object


    Args:
        obj (M): the object to delete

    Returns:
        The literal `True` if the method ran successfuly

    """

    q, vals = queries.for_delete_one(obj)
    try:
        self.connection.execute(q, vals)
        self.connection.commit()
    except:
        raise disconnected_engine_error
    return True

get_all()

Gets all objects from the database

Returns:

Type Description
list[M]

A list with all the rows in table as instances of the model

Source code in ardilla/crud.py
156
157
158
159
160
161
def get_all(self) -> list[M]:
    """Gets all objects from the database
    Returns:
        A list with all the rows in table as instances of the model
    """
    return self.get_many()

get_many(order_by=None, limit=None, **kws)

Queries the database and returns objects that meet the criteris

Parameters:

Name Type Description Default
order_by Optional[dict[str, str]]

An ordering dict. Defaults to None. The ordering should have the structure: {'column_name': 'ASC' OR 'DESC'} Case in values is insensitive

None
limit Optional[int]

The number of items to return. Defaults to None.

None
kws SQLFieldType

The column names and values for the select query

{}

Returns:

Type Description
list[M]

a list of rows matching the criteria as intences of the model

Source code in ardilla/crud.py
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
def get_many(
    self,
    order_by: Optional[dict[str, str]] = None,
    limit: Optional[int] = None,
    **kws: SQLFieldType,
) -> list[M]:
    """Queries the database and returns objects that meet the criteris

    Args:
        order_by (Optional[dict[str, str]], optional): An ordering dict. Defaults to None.
            The ordering should have the structure: `{'column_name': 'ASC' OR 'DESC'}`
            Case in values is insensitive

        limit (Optional[int], optional): The number of items to return. Defaults to None.
        kws (SQLFieldType): The column names and values for the select query

    Returns:
        a list of rows matching the criteria as intences of the model
    """
    self.verify_kws(kws)
    q, vals = queries.for_get_many(
        self.Model, 
        order_by=order_by,
        limit=limit, 
        kws=kws,
    )
    with contextcursor(self.connection) as cur:
        cur.execute(q, vals)
        rows: list[Row] = cur.fetchall()
        return [self._row2obj(row) for row in rows]

get_or_create(**kws)

Returns an object from the database with the spefied matching data

Parameters:

Name Type Description Default
kws SQLFieldType

the key value pairs will be used to query for an existing row if no record is found then a new row will be inserted

{}

Returns:

Type Description
tuple[M, bool]

A tuple with two values, the object and a boolean indicating if the object was newly created or not

Source code in ardilla/crud.py
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def get_or_create(self, **kws: SQLFieldType) -> tuple[M, bool]:
    """Returns an object from the database with the spefied matching data
    Args:
        kws (SQLFieldType): the key value pairs will be used to query for an existing row
            if no record is found then a new row will be inserted
    Returns:
        A tuple with two values, the object and a boolean indicating if the
            object was newly created or not
    """
    self.verify_kws(kws)
    created = False
    result = self.get_or_none(**kws)
    if not result:
        result = self.insert_or_ignore(**kws)
        created = True
    return result, created

get_or_none(**kws)

Returns a row as an instance of the model if one is found or none

Parameters:

Name Type Description Default
kws SQLFieldType

The keyword arguments are passed as column names and values to a select query

{}
Example
crud.get_or_none(id=42)

# returns an object with id of 42 or None if there isn't one in the database

Returns:

Type Description
Optional[M]

The object found with the criteria if any

Source code in ardilla/crud.py
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
def get_or_none(self, **kws: SQLFieldType) -> Optional[M]:
    """Returns a row as an instance of the model if one is found or none

    Args:
        kws (SQLFieldType): The keyword arguments are passed as column names and values to
            a select query

    Example:
        ```py
        crud.get_or_none(id=42)

        # returns an object with id of 42 or None if there isn't one in the database
        ```

    Returns:
        The object found with the criteria if any
    """
    self.verify_kws(kws)
    q, vals = queries.for_get_or_none(self.tablename, kws)
    with contextcursor(self.connection) as cur:
        cur.execute(q, vals)
        row: Union[Row, None] = cur.fetchone()
        if row:
            return self._row2obj(row)
    return None

insert(**kws)

Inserts a record into the database.

Parameters:

Name Type Description Default
kws SQLFieldType

The keyword arguments are passed as the column names and values to the insert query

{}

Returns:

Type Description
M

Creates a new entry in the database and returns the object

Rises

ardilla.error.QueryExecutionError: if there's a conflict when inserting the record

Source code in ardilla/crud.py
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
def insert(self, **kws: SQLFieldType) -> M:
    """Inserts a record into the database.

    Args:
        kws (SQLFieldType): The keyword arguments are passed as the column names and values
            to the insert query

    Returns:
        Creates a new entry in the database and returns the object

    Rises:
        `ardilla.error.QueryExecutionError`: if there's a conflict when inserting the record
    """
    self.verify_kws(kws)
    return self._do_insert(False, True, **kws)

insert_or_ignore(**kws)

Inserts a record to the database with the keywords passed. It ignores conflicts.

Parameters:

Name Type Description Default
kws SQLFieldType

The keyword arguments are passed as the column names and values to the insert query

{}

Returns:

Type Description
Optional[M]

The newly created row as an instance of the model if there was no conflicts

Source code in ardilla/crud.py
100
101
102
103
104
105
106
107
108
109
110
111
def insert_or_ignore(self, **kws: SQLFieldType) -> Optional[M]:
    """Inserts a record to the database with the keywords passed. It ignores conflicts.

    Args:
        kws (SQLFieldType): The keyword arguments are passed as the column names and values
            to the insert query

    Returns:
        The newly created row as an instance of the model if there was no conflicts
    """
    self.verify_kws(kws)
    return self._do_insert(True, True, **kws)

save_many(*objs)

Saves all the passed objects to the database

Parameters:

Name Type Description Default
objs M

the objects to persist

()

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/crud.py
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
def save_many(self, *objs: tuple[M]) -> Literal[True]:
    """Saves all the passed objects to the database

    Args:
        objs (M): the objects to persist

    Returns:
        The literal `True` if the method ran successfuly
    """
    q, vals = queries.for_save_many(objs)
    try:
        self.connection.executemany(q, vals)
        self.connection.commit()
    except:
        raise disconnected_engine_error

    return True

save_one(obj)

Saves one object to the database

Parameters:

Name Type Description Default
obj M

the object to persist

required

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/crud.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
def save_one(self, obj: M) -> Literal[True]:
    """Saves one object to the database

    Args:
        obj (M): the object to persist

    Returns:
        The literal `True` if the method ran successfuly
    """
    q, vals = queries.for_save_one(obj)
    try:
        self.connection.execute(q, vals)
        self.connection.commit()
    except:
        raise disconnected_engine_error
    return True

Async CRUD

Bases: BaseCrud, Generic[M]

Abstracts CRUD actions for model associated tables

Source code in ardilla/asyncio/crud.py
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
class AsyncCrud(BaseCrud, Generic[M]):
    """Abstracts CRUD actions for model associated tables"""
    connection: aiosqlite.Connection

    def __init__(self, Model: type[M], connection: aiosqlite.Connection) -> None:
        connection = ConnectionProxy(connection)
        super().__init__(Model, connection)


    async def _do_insert(
        self,
        ignore: bool = False,
        returning: bool = True,
        /,
        **kws: SQLFieldType,
    ):
        """private helper method for insertion methods

        Args:
            ignore (bool, optional): Ignores conflicts silently. Defaults to False.
            returning (bool, optional): Determines if the query should return the inserted row. Defaults to True.
            kws (SQLFieldType): the column names and values for the insertion query

        Raises:
            QueryExecutionError: when sqlite3.IntegrityError happens because of a conflic

        Returns:
            An instance of model if any row is returned
        """
        q, vals = queries.for_do_insert(self.tablename, ignore, returning, kws)

        cur = None
        try:
            cur = await self.connection.execute(q, vals)
        except aiosqlite.IntegrityError as e:
            raise QueryExecutionError(str(e))
        except aiosqlite.ProgrammingError as e:
            raise disconnected_engine_error
        else:
            row = await cur.fetchone()
            await self.connection.commit()
            if returning and row:
                return self._row2obj(row, cur.lastrowid)
        finally:
            if cur is not None:
                await cur.close()

    async def get_or_none(self, **kws: SQLFieldType) -> Optional[M]:
        """Returns a row as an instance of the model if one is found or none

        Args:
            kws (SQLFieldType): The keyword arguments are passed as column names and values to
                a select query

        Example:
            ```py
            await crud.get_or_none(id=42)

            # returns an object with id of 42 or None if there isn't one in the database
            ```
        Returns:
            The object found with the criteria if any
        """
        self.verify_kws(kws)
        q, vals = queries.for_get_or_none(self.tablename, kws)

        async with self.connection.execute(q, vals) as cur:
            row: Union[Row, None] = await cur.fetchone()
            if row:
                return self._row2obj(row)
        return None

    async def insert(self, **kws: SQLFieldType) -> M:
        """
        Inserts a record into the database.

        Args:
            kws (SQLFieldType): the column names and values for the insertion query

        Returns:
            Returns the inserted row as an instance of the model
        Rises:
            ardilla.error.QueryExecutionError: if there's a conflict when inserting the record
        """
        self.verify_kws(kws)
        return await self._do_insert(False, True, **kws)

    async def insert_or_ignore(self, **kws: SQLFieldType) -> Optional[M]:
        """Inserts a record to the database with the keywords passed. It ignores conflicts.

        Args:
            kws (SQLFieldType): The keyword arguments are passed as the column names and values
                to the insert query

        Returns:
            The newly created row as an instance of the model if there was no conflicts
        """
        self.verify_kws(kws)
        return await self._do_insert(True, True, **kws)

    async def get_or_create(self, **kws: SQLFieldType) -> tuple[M, bool]:
        """Returns an object from the database with the spefied matching data
        Args:
            kws (SQLFieldType): the key value pairs will be used to query for an existing row
                if no record is found then a new row will be inserted
        Returns:
            A tuple with two values, the object and a boolean indicating if the
                object was newly created or not
        """
        created = False
        result = await self.get_or_none(**kws)
        if not result:
            result = await self.insert_or_ignore(**kws)
            created = True
        return result, created

    async def get_all(self) -> list[M]:
        """Gets all objects from the database

        Returns:
            A list with all the rows in table as instances of the model
        """
        q = f"SELECT rowid, * FROM {self.tablename};"

        async with self.connection.execute(q) as cur:
            return [self._row2obj(row) for row in await cur.fetchall()]

    async def get_many(
        self,
        order_by: Optional[dict[str, str]] = None,
        limit: Optional[int] = None,
        **kws: SQLFieldType,
    ) -> list[M]:
        """Queries the database and returns objects that meet the criteris

        Args:
            order_by (Optional[dict[str, str]], optional): An ordering dict. Defaults to None.
                The ordering should have the structure: `{'column_name': 'ASC' OR 'DESC'}`
                Case in values is insensitive
            kws (SQLFieldType): the column names and values for the select query

            limit (Optional[int], optional): The number of items to return. Defaults to None.

        Returns:
            a list of rows matching the criteria as intences of the model
        """
        self.verify_kws(kws)

        q, vals = queries.for_get_many(
            self.Model, order_by=order_by, limit=limit, kws=kws
        )
        async with self.connection.execute(q, vals) as cur:
            rows: list[Row] = await cur.fetchall()
            return [self._row2obj(row) for row in rows]

    async def save_one(self, obj: M) -> Literal[True]:
        """Saves one object to the database

        Args:
            obj (M): the object to persist

        Returns:
            The literal `True` if the method ran successfuly
        """
        q, vals = queries.for_save_one(obj)

        await self.connection.execute(q, vals)
        await self.connection.commit()
        return True

    async def save_many(self, *objs: M) -> Literal[True]:
        """Saves all the passed objects to the database

        Args:
            objs (M): the objects to persist

        Returns:
            The literal `True` if the method ran successfuly
        """
        q, vals = queries.for_save_many(objs)

        await self.connection.executemany(q, vals)
        await self.connection.commit()

        return True

    async def delete_one(self, obj: M) -> Literal[True]:
        """
        Deletes the object from the database (won't delete the actual object)
        If the object has a PK field or the rowid setup, those will be
        used to locate the obj and delete it.
        If not, this function will delete any row that meets the values of the object


        Args:
            obj (M): the object to delete

        Returns:
            The literal `True` if the method ran successfuly

        """
        q, vals = queries.for_delete_one(obj)

        await self.connection.execute(q, vals)
        await self.connection.commit()
        return True

    async def delete_many(self, *objs: M) -> Literal[True]:
        """
        Deletes all the objects passed

        Args:
            objs (M): the object to delete

        Returns:
            The literal `True` if the method ran successfuly

        """
        q, vals = queries.for_delete_many(objs)

        await self.connection.execute(q, vals)
        await self.connection.commit()

    async def count(self, column: str = '*', /, **kws) -> int:
        """Returns an integer of the number of non null values in a column
        Or the total number of rows if '*' is passed

        Args:
            column (str, optional): The column name to count rows on. 
                Defaults to '*' which counts all the rows in the table

        Returns:
            int: the number of rows with non null values in a column or the number of rows in a table
        """
        tablename = self.Model.__tablename__
        if column not in self.Model.__fields__ and column != '*':
            raise BadQueryError(f'"{column}" is not a field of the "{tablename}" table')

        q, vals = queries.for_count(tablename, column, kws)
        async with self.connection.execute(q, vals) as cur:
            row = await cur.fetchone()    
            count = row['total_count']

        return count

count(column='*', /, **kws) async

Returns an integer of the number of non null values in a column Or the total number of rows if '*' is passed

Parameters:

Name Type Description Default
column str

The column name to count rows on. Defaults to '*' which counts all the rows in the table

'*'

Returns:

Name Type Description
int int

the number of rows with non null values in a column or the number of rows in a table

Source code in ardilla/asyncio/crud.py
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
async def count(self, column: str = '*', /, **kws) -> int:
    """Returns an integer of the number of non null values in a column
    Or the total number of rows if '*' is passed

    Args:
        column (str, optional): The column name to count rows on. 
            Defaults to '*' which counts all the rows in the table

    Returns:
        int: the number of rows with non null values in a column or the number of rows in a table
    """
    tablename = self.Model.__tablename__
    if column not in self.Model.__fields__ and column != '*':
        raise BadQueryError(f'"{column}" is not a field of the "{tablename}" table')

    q, vals = queries.for_count(tablename, column, kws)
    async with self.connection.execute(q, vals) as cur:
        row = await cur.fetchone()    
        count = row['total_count']

    return count

delete_many(*objs) async

Deletes all the objects passed

Parameters:

Name Type Description Default
objs M

the object to delete

()

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/asyncio/crud.py
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
async def delete_many(self, *objs: M) -> Literal[True]:
    """
    Deletes all the objects passed

    Args:
        objs (M): the object to delete

    Returns:
        The literal `True` if the method ran successfuly

    """
    q, vals = queries.for_delete_many(objs)

    await self.connection.execute(q, vals)
    await self.connection.commit()

delete_one(obj) async

Deletes the object from the database (won't delete the actual object) If the object has a PK field or the rowid setup, those will be used to locate the obj and delete it. If not, this function will delete any row that meets the values of the object

Parameters:

Name Type Description Default
obj M

the object to delete

required

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/asyncio/crud.py
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
async def delete_one(self, obj: M) -> Literal[True]:
    """
    Deletes the object from the database (won't delete the actual object)
    If the object has a PK field or the rowid setup, those will be
    used to locate the obj and delete it.
    If not, this function will delete any row that meets the values of the object


    Args:
        obj (M): the object to delete

    Returns:
        The literal `True` if the method ran successfuly

    """
    q, vals = queries.for_delete_one(obj)

    await self.connection.execute(q, vals)
    await self.connection.commit()
    return True

get_all() async

Gets all objects from the database

Returns:

Type Description
list[M]

A list with all the rows in table as instances of the model

Source code in ardilla/asyncio/crud.py
149
150
151
152
153
154
155
156
157
158
async def get_all(self) -> list[M]:
    """Gets all objects from the database

    Returns:
        A list with all the rows in table as instances of the model
    """
    q = f"SELECT rowid, * FROM {self.tablename};"

    async with self.connection.execute(q) as cur:
        return [self._row2obj(row) for row in await cur.fetchall()]

get_many(order_by=None, limit=None, **kws) async

Queries the database and returns objects that meet the criteris

Parameters:

Name Type Description Default
order_by Optional[dict[str, str]]

An ordering dict. Defaults to None. The ordering should have the structure: {'column_name': 'ASC' OR 'DESC'} Case in values is insensitive

None
kws SQLFieldType

the column names and values for the select query

{}
limit Optional[int]

The number of items to return. Defaults to None.

None

Returns:

Type Description
list[M]

a list of rows matching the criteria as intences of the model

Source code in ardilla/asyncio/crud.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
async def get_many(
    self,
    order_by: Optional[dict[str, str]] = None,
    limit: Optional[int] = None,
    **kws: SQLFieldType,
) -> list[M]:
    """Queries the database and returns objects that meet the criteris

    Args:
        order_by (Optional[dict[str, str]], optional): An ordering dict. Defaults to None.
            The ordering should have the structure: `{'column_name': 'ASC' OR 'DESC'}`
            Case in values is insensitive
        kws (SQLFieldType): the column names and values for the select query

        limit (Optional[int], optional): The number of items to return. Defaults to None.

    Returns:
        a list of rows matching the criteria as intences of the model
    """
    self.verify_kws(kws)

    q, vals = queries.for_get_many(
        self.Model, order_by=order_by, limit=limit, kws=kws
    )
    async with self.connection.execute(q, vals) as cur:
        rows: list[Row] = await cur.fetchall()
        return [self._row2obj(row) for row in rows]

get_or_create(**kws) async

Returns an object from the database with the spefied matching data

Parameters:

Name Type Description Default
kws SQLFieldType

the key value pairs will be used to query for an existing row if no record is found then a new row will be inserted

{}

Returns:

Type Description
tuple[M, bool]

A tuple with two values, the object and a boolean indicating if the object was newly created or not

Source code in ardilla/asyncio/crud.py
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
async def get_or_create(self, **kws: SQLFieldType) -> tuple[M, bool]:
    """Returns an object from the database with the spefied matching data
    Args:
        kws (SQLFieldType): the key value pairs will be used to query for an existing row
            if no record is found then a new row will be inserted
    Returns:
        A tuple with two values, the object and a boolean indicating if the
            object was newly created or not
    """
    created = False
    result = await self.get_or_none(**kws)
    if not result:
        result = await self.insert_or_ignore(**kws)
        created = True
    return result, created

get_or_none(**kws) async

Returns a row as an instance of the model if one is found or none

Parameters:

Name Type Description Default
kws SQLFieldType

The keyword arguments are passed as column names and values to a select query

{}
Example
await crud.get_or_none(id=42)

# returns an object with id of 42 or None if there isn't one in the database

Returns:

Type Description
Optional[M]

The object found with the criteria if any

Source code in ardilla/asyncio/crud.py
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
async def get_or_none(self, **kws: SQLFieldType) -> Optional[M]:
    """Returns a row as an instance of the model if one is found or none

    Args:
        kws (SQLFieldType): The keyword arguments are passed as column names and values to
            a select query

    Example:
        ```py
        await crud.get_or_none(id=42)

        # returns an object with id of 42 or None if there isn't one in the database
        ```
    Returns:
        The object found with the criteria if any
    """
    self.verify_kws(kws)
    q, vals = queries.for_get_or_none(self.tablename, kws)

    async with self.connection.execute(q, vals) as cur:
        row: Union[Row, None] = await cur.fetchone()
        if row:
            return self._row2obj(row)
    return None

insert(**kws) async

Inserts a record into the database.

Parameters:

Name Type Description Default
kws SQLFieldType

the column names and values for the insertion query

{}

Returns:

Type Description
M

Returns the inserted row as an instance of the model

Rises

ardilla.error.QueryExecutionError: if there's a conflict when inserting the record

Source code in ardilla/asyncio/crud.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
async def insert(self, **kws: SQLFieldType) -> M:
    """
    Inserts a record into the database.

    Args:
        kws (SQLFieldType): the column names and values for the insertion query

    Returns:
        Returns the inserted row as an instance of the model
    Rises:
        ardilla.error.QueryExecutionError: if there's a conflict when inserting the record
    """
    self.verify_kws(kws)
    return await self._do_insert(False, True, **kws)

insert_or_ignore(**kws) async

Inserts a record to the database with the keywords passed. It ignores conflicts.

Parameters:

Name Type Description Default
kws SQLFieldType

The keyword arguments are passed as the column names and values to the insert query

{}

Returns:

Type Description
Optional[M]

The newly created row as an instance of the model if there was no conflicts

Source code in ardilla/asyncio/crud.py
120
121
122
123
124
125
126
127
128
129
130
131
async def insert_or_ignore(self, **kws: SQLFieldType) -> Optional[M]:
    """Inserts a record to the database with the keywords passed. It ignores conflicts.

    Args:
        kws (SQLFieldType): The keyword arguments are passed as the column names and values
            to the insert query

    Returns:
        The newly created row as an instance of the model if there was no conflicts
    """
    self.verify_kws(kws)
    return await self._do_insert(True, True, **kws)

save_many(*objs) async

Saves all the passed objects to the database

Parameters:

Name Type Description Default
objs M

the objects to persist

()

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/asyncio/crud.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
async def save_many(self, *objs: M) -> Literal[True]:
    """Saves all the passed objects to the database

    Args:
        objs (M): the objects to persist

    Returns:
        The literal `True` if the method ran successfuly
    """
    q, vals = queries.for_save_many(objs)

    await self.connection.executemany(q, vals)
    await self.connection.commit()

    return True

save_one(obj) async

Saves one object to the database

Parameters:

Name Type Description Default
obj M

the object to persist

required

Returns:

Type Description
Literal[True]

The literal True if the method ran successfuly

Source code in ardilla/asyncio/crud.py
188
189
190
191
192
193
194
195
196
197
198
199
200
201
async def save_one(self, obj: M) -> Literal[True]:
    """Saves one object to the database

    Args:
        obj (M): the object to persist

    Returns:
        The literal `True` if the method ran successfuly
    """
    q, vals = queries.for_save_one(obj)

    await self.connection.execute(q, vals)
    await self.connection.commit()
    return True