Exec: should ErrPktTooLarge be returned for interpolated params instead of db.ErrSkip?
When using a very large interpolated statement, interpolateParams returns db.ErrSkip when the interpolated statement exceeds maxPacketAllowed. Inside database/sql, if ErrSkip is returned, Exec falls back to the prepare/execute cycle and returns any resultant error. Prepared statements have a limit of 65535 statements. Any error other than ErrSkip is returned immediately and no further prepare/execute is attempted.
I use interpolateParams to get statements larger than 65535 statements and to avoid the prepare/execute cycle. Returning ErrPktTooLarge allows users to either trim their packet size (drop the number of params to be interpolated) or to increase the max_allowed_packet inside mysql.
The current behavior is reasonable and acceptable because of the prepare/execute fallback. ErrPktTooLarge is also, in my opinion, reasonable and allows programs to self adjust or fix what they are doing.
Can it be an option to return ErrPktTooLarge?
Alternatively, expose a function that we can pass our statement and arguments to to get what interpolateParams returns. If Exec fails, we can manually check.
I think it isn't suitable for connection level option specified by dsl. Since It's rare case that programmer modify query manually.
There are two ideas.
- Add API like
mysql.InterpolateParams(db *sql.DB, query string, args... interface{}) (string, error). It fetches options and variables fromdb. - Add struct like
mysql.ExecuteOption{FallbackOnInterpolatedQueryIsTooLarge bool, ...}and it can be passed as the first argument ofdb.Exec()anddb.Query(). e.g.db.Query(query, &option, largeArgs...).
I don't really see the benefit in the struct and it will probably be impossible to implement it in a sensible way thanks to the restrictiveness of database/sql: https://github.com/golang/go/blob/master/src/database/sql/convert.go#L73 (and L53). That means only bool, []byte, float64, int64, string and time.Time can be passed as arguments.
I think we should go with option 1.