(db SqlPreparer)
| 159 | } |
| 160 | |
| 161 | func (c *Cursor) Fetch(db SqlPreparer) (batch *RowBatch, paginationKeypos PaginationKey, err error) { |
| 162 | var selectBuilder squirrel.SelectBuilder |
| 163 | batchSize := c.CursorConfig.GetBatchSize(c.Table.Schema, c.Table.Name) |
| 164 | |
| 165 | if c.BuildSelect != nil { |
| 166 | selectBuilder, err = c.BuildSelect(c.ColumnsToSelect, c.Table, c.lastSuccessfulPaginationKey, batchSize) |
| 167 | if err != nil { |
| 168 | c.logger.WithError(err).Error("failed to apply filter for select") |
| 169 | return |
| 170 | } |
| 171 | } else { |
| 172 | selectBuilder = DefaultBuildSelect(c.ColumnsToSelect, c.Table, c.lastSuccessfulPaginationKey, batchSize) |
| 173 | } |
| 174 | |
| 175 | if c.RowLock { |
| 176 | mySqlVersion, err := c.DB.QueryMySQLVersion() |
| 177 | if err != nil { |
| 178 | return nil, NewUint64Key(0), err |
| 179 | } |
| 180 | if strings.HasPrefix(mySqlVersion, "8.") { |
| 181 | selectBuilder = selectBuilder.Suffix("FOR SHARE NOWAIT") |
| 182 | } else { |
| 183 | selectBuilder = selectBuilder.Suffix("LOCK IN SHARE MODE") |
| 184 | } |
| 185 | } |
| 186 | |
| 187 | query, args, err := selectBuilder.ToSql() |
| 188 | if err != nil { |
| 189 | c.logger.WithError(err).Error("failed to build chunking sql") |
| 190 | return |
| 191 | } |
| 192 | |
| 193 | // With the inline verifier, the columns to be selected may be very large as |
| 194 | // the query generated will be very large. The code here simply hides the |
| 195 | // columns from the logger to not spam the logs. |
| 196 | |
| 197 | splitQuery := strings.Split(query, "FROM") |
| 198 | loggedQuery := fmt.Sprintf("SELECT [omitted] FROM %s", splitQuery[1]) |
| 199 | |
| 200 | logger := c.logger.WithFields(Fields{ |
| 201 | "sql": loggedQuery, |
| 202 | "args": args, |
| 203 | }) |
| 204 | |
| 205 | // This query must be a prepared query. If it is not, querying will use |
| 206 | // MySQL's plain text interface, which will scan all values into []uint8 |
| 207 | // if we give it []interface{}. |
| 208 | stmt, err := db.Prepare(query) |
| 209 | if err != nil { |
| 210 | logger.WithError(err).Error("failed to prepare query") |
| 211 | return |
| 212 | } |
| 213 | |
| 214 | defer stmt.Close() |
| 215 | |
| 216 | rows, err := stmt.Query(args...) |
| 217 | if err != nil { |
| 218 | logger.WithError(err).Error("failed to query database") |
no test coverage detected