| // Copyright 2026 The Go-MySQL-Driver Authors. All rights reserved. | |
| // | |
| // This Source Code Form is subject to the terms of the Mozilla Public | |
| // License, v. 2.0. If a copy of the MPL was not distributed with this file, | |
| // You can obtain one at http://mozilla.org/MPL/2.0/. | |
| // Package zstd enables automatic Zstandard compression for MySQL connections | |
| // with compression enabled. Import it for its side effects: | |
| // | |
| // import _ "github.com/go-sql-driver/mysql/zstd" | |
| // | |
| // This also registers the mysql database/sql driver. Connections use zstd when | |
| // the server supports it and fall back to zlib otherwise. Compression remains | |
| // disabled unless enabled through the DSN or mysql.EnableCompression. | |
| package zstd | |
| import ( | |
| "sync" | |
| _ "github.com/go-sql-driver/mysql" | |
| "github.com/go-sql-driver/mysql/internal/compression" | |
| "github.com/klauspost/compress/zstd" | |
| ) | |
| // Protocol packets have a three-byte uncompressed length. Bound both decoded | |
| // output and the frame window; codec defaults allow much larger allocations. | |
| const maxPacketSize = 1<<24 - 1 | |
| var encoderPool = sync.Pool{New: func() any { | |
| encoder, err := zstd.NewWriter(nil, | |
| zstd.WithEncoderConcurrency(1), | |
| // Fixed level 3 balances compression ratio and speed, favoring speed. | |
| // Importing this package alone does not enable compression. | |
| zstd.WithEncoderLevel(zstd.EncoderLevelFromZstd(compression.ZstdLevel)), | |
| ) | |
| if err != nil { | |
| panic(err) // All options are fixed and valid. | |
| } | |
| return encoder | |
| }} | |
| var decoderPool = sync.Pool{New: func() any { | |
| decoder, err := zstd.NewReader(nil, | |
| zstd.WithDecoderConcurrency(1), | |
| zstd.WithDecoderMaxMemory(maxPacketSize), | |
| zstd.WithDecoderMaxWindow(1<<24), | |
| zstd.WithDecodeAllCapLimit(true), | |
| ) | |
| if err != nil { | |
| panic(err) // All options are fixed and valid. | |
| } | |
| return decoder | |
| }} | |
| type codec struct{} | |
| func (codec) Encode(src, dst []byte) []byte { | |
| encoder := encoderPool.Get().(*zstd.Encoder) | |
| dst = encoder.EncodeAll(src, dst) | |
| encoderPool.Put(encoder) | |
| return dst | |
| } | |
| func (codec) Decode(src, dst []byte) ([]byte, error) { | |
| decoder := decoderPool.Get().(*zstd.Decoder) | |
| dst, err := decoder.DecodeAll(src, dst) | |
| decoderPool.Put(decoder) | |
| return dst, err | |
| } | |
| func init() { | |
| compression.Zstd = codec{} | |
| } |