File: cursors.rst

package info (click to toggle)
aiomysql 0.1.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, sid, trixie
  • size: 912 kB
  • sloc: python: 6,894; makefile: 213
file content (390 lines) | stat: -rw-r--r-- 14,388 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
.. _aiomysql-cursors:

Cursor
======

.. class:: Cursor

    A cursor for connection.

    Allows Python code to execute :term:`MySQL` command in a database
    session. Cursors are created by the :meth:`Connection.cursor`
    :ref:`coroutine <coroutine>`: they are bound to the connection for
    the entire lifetime and all the commands are executed in the context
    of the database session wrapped by the connection.

    Cursors that are created from the same connection are not isolated,
    i.e., any changes done to the database by a cursor are immediately
    visible by the other cursors. Cursors created from different
    connections can or can not be isolated, depending on the
    connections’ isolation level.

    .. code:: python

        import asyncio
        import aiomysql

        loop = asyncio.get_event_loop()

        async def test_example():
            conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                          user='root', password='',
                                          db='mysql', loop=loop)

            # create default cursor
            cursor = await conn.cursor()

            # execute sql query
            await cursor.execute("SELECT Host, User FROM user")

            # fetch all results
            r = await cursor.fetchall()

            # detach cursor from connection
            await cursor.close()

            # close connection
            conn.close()

        loop.run_until_complete(test_example())


    Use :meth:`Connection.cursor()` for getting cursor for connection.

    .. attribute:: connection

        This read-only attribute return a reference to the :class:`Connection`
        object on which the cursor was created

    .. attribute:: echo

        Return echo mode status.

   .. attribute:: description

        This read-only attribute is a sequence of 7-item sequences.

        Each of these sequences is a collections.namedtuple containing
        information describing one result column:

        0.  name: the name of the column returned.
        1.  type_code: the type of the column.
        2.  display_size: the actual length of the column in bytes.
        3.  internal_size: the size in bytes of the column associated to
            this column on the server.
        4.  precision: total number of significant digits in columns of
            type ``NUMERIC``. None for other types.
        5.  scale: count of decimal digits in the fractional part in
            columns of type ``NUMERIC``. None for other types.
        6.  null_ok: always None.

        This attribute will be None for operations that do not
        return rows or if the cursor has not had an operation invoked
        via the :meth:`Cursor.execute()` method yet.

   .. attribute:: rowcount

        Returns the number of rows that has been produced of affected.

        This read-only attribute specifies the number of rows that the
        last :meth:`Cursor.execute()` produced (for Data Query Language
        statements like SELECT) or affected (for Data Manipulation
        Language statements like ``UPDATE`` or ``INSERT``).

        The attribute is -1 in case no :meth:`Cursor.execute()` has been
        performed on the cursor or the row count of the last operation if it
        can't be determined by the interface.

   .. attribute:: rownumber

        Row index. This read-only attribute provides the current 0-based index
        of the cursor in the result set or ``None`` if the index cannot be
        determined.

   .. attribute:: arraysize

        How many rows will be returned by :meth:`Cursor.fetchmany()` call.

        This read/write attribute specifies the number of rows to
        fetch at a time with :meth:`Cursor.fetchmany()`. It defaults to
        1 meaning to fetch a single row at a time.

   .. attribute:: lastrowid

        This read-only property returns the value generated for an
        `AUTO_INCREMENT` column by the previous `INSERT` or `UPDATE` statement
        or None when there is no such value available. For example,
        if you perform an `INSERT` into a table that contains an
        `AUTO_INCREMENT` column, :attr:`Cursor.lastrowid` returns the
        `AUTO_INCREMENT` value for the new row.

   .. attribute:: closed

        The readonly property that returns ``True`` if connections was detached
        from current cursor

   .. method:: close()

        :ref:`Coroutine <coroutine>` to close the cursor now (rather than
        whenever ``del`` is executed). The cursor will be unusable from this
        point forward; closing a cursor just exhausts all remaining data.

   .. method:: execute(query, args=None)

        :ref:`Coroutine <coroutine>`, executes the given operation substituting
        any markers with the given parameters.

        For example, getting all rows where id is 5::

            await cursor.execute("SELECT * FROM t1 WHERE id=%s", (5,))

        :param str query: sql statement
        :param list args: tuple or list of arguments for sql query
        :returns int: number of rows that has been produced of affected

   .. method:: executemany(query, args)

        The `executemany()` :ref:`coroutine <coroutine>` will execute the
        operation iterating over the list of parameters in seq_params.

        Example: Inserting 3 new employees and their phone number::

            data = [
                ('Jane','555-001'),
                ('Joe', '555-001'),
                ('John', '555-003')
               ]
            stmt = "INSERT INTO employees (name, phone)
                VALUES ('%s','%s')"
            await cursor.executemany(stmt, data)

        `INSERT` statements are optimized by batching the data, that is
        using the MySQL multiple rows syntax.

        :param str  query: sql statement
        :param list args: tuple or list of arguments for sql query

   .. method:: callproc(procname, args)

        Execute  stored procedure procname with args, this method is
        :ref:`coroutine <coroutine>`.

        Compatibility warning: PEP-249 specifies that any modified
        parameters must be returned. This is currently impossible
        as they are only available by storing them in a server
        variable and then retrieved by a query. Since stored
        procedures return zero or more result sets, there is no
        reliable way to get at OUT or INOUT parameters via `callproc`.
        The server variables are named `@_procname_n`, where `procname`
        is the parameter above and n is the position of the parameter
        (from zero). Once all result sets generated by the procedure
        have been fetched, you can issue a `SELECT @_procname_0`, ...
        query using :meth:`Cursor.execute()` to get any OUT or INOUT values.
        Basic usage example::

            conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                          user='root', password='',
                                          db='mysql', loop=self.loop)

            cur = await conn.cursor()
            await cur.execute("""CREATE PROCEDURE myinc(p1 INT)
                              BEGIN
                                  SELECT p1 + 1;
                              END
                              """)

            await cur.callproc('myinc', [1])
            (ret, ) = await cur.fetchone()
            assert 2, ret

            await cur.close()
            conn.close()

        Compatibility warning: The act of calling a stored procedure
        itself creates an empty result set. This appears after any
        result sets generated by the procedure. This is non-standard
        behavior with respect to the DB-API. Be sure to use
        :meth:`Cursor.nextset()` to advance through all result sets; otherwise
        you may get disconnected.

        :param str procname: name of procedure to execute on server
        :param args: sequence of parameters to use with procedure
        :returns: the original args.

   .. method:: fetchone()

        Fetch the next row :ref:`coroutine <coroutine>`.

   .. method:: fetchmany(size=None)

        :ref:`Coroutine <coroutine>` the next set of rows of a query result,
        returning a list of tuples. When no more rows are available, it
        returns an empty list.

        The number of rows to fetch per call is specified by the parameter.
        If it is not given, the cursor's :attr:`Cursor.arraysize` determines
        the number of rows to be fetched. The method should try to fetch as
        many rows as indicated by the size parameter. If this is not possible
        due to the specified number of rows not being available, fewer rows
        may be returned ::

            cursor = await connection.cursor()
            await cursor.execute("SELECT * FROM test;")
            r = cursor.fetchmany(2)
            print(r)
            # [(1, 100, "abc'def"), (2, None, 'dada')]
            r = await cursor.fetchmany(2)
            print(r)
            # [(3, 42, 'bar')]
            r = await cursor.fetchmany(2)
            print(r)
            # []

        :param int size: number of rows to return
        :returns list: of fetched rows

   .. method:: fetchall()

        :ref:`Coroutine <coroutine>` returns all rows of a query result set::

         await cursor.execute("SELECT * FROM test;")
         r = await cursor.fetchall()
         print(r)
         # [(1, 100, "abc'def"), (2, None, 'dada'), (3, 42, 'bar')]

        :returns list: list of fetched rows

   .. method:: scroll(value, mode='relative')

        Scroll the cursor in the result set to a new position according
        to mode. This method is :ref:`coroutine <coroutine>`.

        If mode is ``relative`` (default), value is taken as offset to the
        current position in the result set, if set to ``absolute``, value
        states an absolute target position. An IndexError should be raised in
        case a scroll operation would leave the result set. In this case,
        the cursor position is left undefined (ideal would be to
        not move the cursor at all).

        .. note::

            According to the :term:`DBAPI`, the exception raised for a cursor out
            of bound should have been :exc:`IndexError`.  The best option is
            probably to catch both exceptions in your code::

                try:
                    await cur.scroll(1000 * 1000)
                except (ProgrammingError, IndexError), exc:
                    deal_with_it(exc)

        :param int value: move cursor to next position according to mode.
        :param str mode: scroll mode, possible modes: `relative` and `absolute`


.. class:: DictCursor

    A cursor which returns results as a dictionary. All methods and arguments
    same as :class:`Cursor`, see example::

        import asyncio
        import aiomysql

        loop = asyncio.get_event_loop()

        async def test_example():
            conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                          user='root', password='',
                                          db='mysql', loop=loop)

            # create dict cursor
            cursor = await conn.cursor(aiomysql.DictCursor)

            # execute sql query
            await cursor.execute(
                "SELECT * from people where name='bob'")

            # fetch all results
            r = await cursor.fetchone()
            print(r)
            # {'age': 20, 'DOB': datetime.datetime(1990, 2, 6, 23, 4, 56),
            # 'name': 'bob'}

        loop.run_until_complete(test_example())

    You can customize your dictionary, see example::

        import asyncio
        import aiomysql

        class AttrDict(dict):
            """Dict that can get attribute by dot, and doesn't raise KeyError"""

            def __getattr__(self, name):
                try:
                    return self[name]
                except KeyError:
                    return None

        class AttrDictCursor(aiomysql.DictCursor):
            dict_type = AttrDict

        loop = asyncio.get_event_loop()

        async def test_example():
            conn = await aiomysql.connect(host='127.0.0.1', port=3306,
                                          user='root', password='',
                                          db='mysql', loop=loop)

            # create your dict cursor
            cursor = await conn.cursor(AttrDictCursor)

            # execute sql query
            await cursor.execute(
                "SELECT * from people where name='bob'")

            # fetch all results
            r = await cursor.fetchone()
            print(r)
            # {'age': 20, 'DOB': datetime.datetime(1990, 2, 6, 23, 4, 56),
            # 'name': 'bob'}
            print(r.age)
            # 20
            print(r.foo)
            # None

        loop.run_until_complete(test_example())


.. class:: SSCursor

    Unbuffered Cursor, mainly useful for queries that return a lot of
    data, or for connections to remote servers over a slow network.

    Instead of copying every row of data into a buffer, this will fetch
    rows as needed. The upside of this, is the client uses much less memory,
    and rows are returned much faster when traveling over a slow network,
    or if the result set is very big.

    There are limitations, though. The MySQL protocol doesn't support
    returning the total number of rows, so the only way to tell how many rows
    there are is to iterate over every row returned. Also, it currently isn't
    possible to scroll backwards, as only the current row is held in memory.
    All methods are the same as in :class:`Cursor` but with different
    behaviour.

   .. method:: fetchall()
        Same as :meth:`Cursor.fetchall` :ref:`coroutine <coroutine>`,
        useless for large queries, as all rows fetched one by one.

   .. method:: fetchmany(size=None, mode='relative')
        Same as :meth:`Cursor.fetchall`, but each row fetched one by one.

   .. method:: scroll(size=None)
        Same as :meth:`Cursor.scroll`, but move cursor on server side one by
        one. If you want to move 20 rows forward scroll will make 20 queries
        to move cursor. Currently only forward scrolling is supported.


.. class:: SSDictCursor

    An unbuffered cursor, which returns results as a dictionary.