(rows *stdsql.Rows, schema sql.Schema)
| 50 | // current session. Non-row results and sessions with no limit are unchanged. |
| 51 | func ApplyQueryRowLimit(ctx *sql.Context, schema sql.Schema, iter sql.RowIter) sql.RowIter { |
| 52 | if iter == nil || schema == nil || types.IsOkResultSchema(schema) { |
| 53 | return iter |
| 54 | } |
| 55 | sess, ok := ctx.Session.(interface{ QueryRowLimit() uint64 }) |
| 56 | if !ok || sess.QueryRowLimit() == 0 { |
| 57 | return iter |
| 58 | } |
| 59 | return &queryRowLimitIter{child: iter, limit: sess.QueryRowLimit()} |
| 60 | } |
| 61 | |
| 62 | func (iter *queryRowLimitIter) Next(ctx *sql.Context) (sql.Row, error) { |
| 63 | if iter.overflowErr != nil { |
| 64 | return nil, iter.overflowErr |
| 65 | } |
| 66 | if iter.closed { |
| 67 | return nil, io.EOF |
| 68 | } |
| 69 | if iter.rows < iter.limit { |
| 70 | row, err := iter.child.Next(ctx) |
| 71 | if err == nil { |
| 72 | iter.rows++ |
| 73 | } |
| 74 | return row, err |
| 75 | } |
| 76 | |
| 77 | _, err := iter.child.Next(ctx) |
| 78 | if err != nil { |
| 79 | return nil, err |
| 80 | } |
| 81 | |
| 82 | limitErr := fmt.Errorf(queryRowLimitError, iter.limit) |
| 83 | iter.overflowErr = errors.Join(limitErr, iter.Close(ctx)) |
| 84 | return nil, iter.overflowErr |
| 85 | } |
| 86 | |
| 87 | func (iter *queryRowLimitIter) Close(ctx *sql.Context) error { |
| 88 | if iter.closed { |
| 89 | return nil |
| 90 | } |
| 91 | iter.closed = true |
| 92 | iter.closeErr = iter.child.Close(ctx) |
| 93 | return iter.closeErr |
| 94 | } |
| 95 | |
| 96 | type typeConversion struct { |
| 97 | idx int |
| 98 | kind reflect.Kind |
| 99 | } |
| 100 | |
| 101 | // SQLRowIter wraps a standard sql.Rows as a RowIter. |
| 102 | type SQLRowIter struct { |
| 103 | rows *stdsql.Rows |
| 104 | columns []*stdsql.ColumnType |
| 105 | schema sql.Schema |
| 106 | buffer []any // pre-allocated buffer for scanning values |
| 107 | pointers []any // pointers to the buffer |
| 108 | decimals []int |
| 109 | intervals []int |
no test coverage detected