Skip to content

Commit 467db65

Browse files
committed
Support EXECUTE IMMEDIATE
Use EXECUTE IMMEDIATE sent in the HTTP request body, instead of putting the query text in HTTP headers. This should allow sending large query text. It can be enabled by setting the `explicitPrepare` option to false in the connection string.
1 parent d71f0cb commit 467db65

File tree

4 files changed

+50
-6
lines changed

4 files changed

+50
-6
lines changed

trino/etc/config.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ http-server.https.port=8443
1212
http-server.authentication.allow-insecure-over-http=true
1313
http-server.https.keystore.path=/etc/trino/secrets/certificate_with_key.pem
1414
internal-communication.shared-secret=gotrino
15+
16+
query.max-length=5000043

trino/etc/jvm.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
-Xmx1G
1+
-Xmx4G
22
-XX:+UseG1GC
33
-XX:G1HeapRegionSize=32M
44
-XX:+UseGCOverheadLimit

trino/integration_test.go

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"math/big"
3535
"net/http"
3636
"os"
37+
"strconv"
3738
"strings"
3839
"testing"
3940
"time"
@@ -75,6 +76,9 @@ func TestMain(m *testing.M) {
7576
flag.Parse()
7677
DefaultQueryTimeout = *integrationServerQueryTimeout
7778
DefaultCancelQueryTimeout = *integrationServerQueryTimeout
79+
if *trinoImageTagFlag == "" {
80+
*trinoImageTagFlag = "latest"
81+
}
7882

7983
var err error
8084
if *integrationServerFlag == "" && !testing.Short() {
@@ -97,9 +101,6 @@ func TestMain(m *testing.M) {
97101
if err != nil {
98102
log.Fatalf("Could not generate TLS certificates: %s", err)
99103
}
100-
if *trinoImageTagFlag == "" {
101-
*trinoImageTagFlag = "latest"
102-
}
103104
resource, err = pool.RunWithOptions(&dt.RunOptions{
104105
Name: name,
105106
Repository: "trinodb/trino",
@@ -1112,3 +1113,29 @@ func TestIntegrationDayToHourIntervalMilliPrecision(t *testing.T) {
11121113
})
11131114
}
11141115
}
1116+
1117+
func TestIntegrationLargeQuery(t *testing.T) {
1118+
version, err := strconv.Atoi(*trinoImageTagFlag)
1119+
if (err != nil && *trinoImageTagFlag != "latest") || (err == nil && version < 418) {
1120+
t.Skip("Skipping test when not using Trino 418 or later.")
1121+
}
1122+
dsn := *integrationServerFlag
1123+
dsn += "?explicitPrepare=false"
1124+
db := integrationOpen(t, dsn)
1125+
defer db.Close()
1126+
rows, err := db.Query("SELECT ?, '"+strings.Repeat("a", 5000000)+"'", 42)
1127+
if err != nil {
1128+
t.Fatal(err)
1129+
}
1130+
defer rows.Close()
1131+
count := 0
1132+
for rows.Next() {
1133+
count++
1134+
}
1135+
if rows.Err() != nil {
1136+
t.Fatal(err)
1137+
}
1138+
if count != 1 {
1139+
t.Fatal("not enough rows returned:", count)
1140+
}
1141+
}

trino/trino.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ const (
141141
sslCertPathConfig = "SSLCertPath"
142142
sslCertConfig = "SSLCert"
143143
accessTokenConfig = "accessToken"
144+
explicitPrepareConfig = "explicitPrepare"
144145
)
145146

146147
var (
@@ -282,6 +283,7 @@ type Conn struct {
282283
kerberosRemoteServiceName string
283284
progressUpdater ProgressUpdater
284285
progressUpdaterPeriod queryProgressCallbackPeriod
286+
useExplicitPrepare bool
285287
}
286288

287289
var (
@@ -298,6 +300,10 @@ func newConn(dsn string) (*Conn, error) {
298300
query := serverURL.Query()
299301

300302
kerberosEnabled, _ := strconv.ParseBool(query.Get(kerberosEnabledConfig))
303+
useExplicitPrepare := true
304+
if query.Get(explicitPrepareConfig) != "" {
305+
useExplicitPrepare, _ = strconv.ParseBool(query.Get(explicitPrepareConfig))
306+
}
301307

302308
var kerberosClient *client.Client
303309

@@ -356,6 +362,7 @@ func newConn(dsn string) (*Conn, error) {
356362
kerberosClient: kerberosClient,
357363
kerberosEnabled: kerberosEnabled,
358364
kerberosRemoteServiceName: query.Get(kerberosRemoteServiceNameConfig),
365+
useExplicitPrepare: useExplicitPrepare,
359366
}
360367

361368
var user string
@@ -867,7 +874,7 @@ func (st *driverStmt) exec(ctx context.Context, args []driver.NamedValue) (*stmt
867874

868875
hs.Add(arg.Name, headerValue)
869876
} else {
870-
if hs.Get(preparedStatementHeader) == "" {
877+
if st.conn.useExplicitPrepare && hs.Get(preparedStatementHeader) == "" {
871878
for _, v := range st.conn.httpHeaders.Values(preparedStatementHeader) {
872879
hs.Add(preparedStatementHeader, v)
873880
}
@@ -880,7 +887,11 @@ func (st *driverStmt) exec(ctx context.Context, args []driver.NamedValue) (*stmt
880887
return nil, ErrInvalidProgressCallbackHeader
881888
}
882889
if len(ss) > 0 {
883-
query = "EXECUTE " + preparedStatementName + " USING " + strings.Join(ss, ", ")
890+
if st.conn.useExplicitPrepare {
891+
query = "EXECUTE " + preparedStatementName + " USING " + strings.Join(ss, ", ")
892+
} else {
893+
query = "EXECUTE IMMEDIATE " + formatStringLiteral(st.query) + " USING " + strings.Join(ss, ", ")
894+
}
884895
}
885896
}
886897

@@ -1028,6 +1039,10 @@ func (st *driverStmt) exec(ctx context.Context, args []driver.NamedValue) (*stmt
10281039
return &sr, handleResponseError(resp.StatusCode, sr.Error)
10291040
}
10301041

1042+
func formatStringLiteral(query string) string {
1043+
return "'" + strings.ReplaceAll(query, "'", "''") + "'"
1044+
}
1045+
10311046
type driverRows struct {
10321047
ctx context.Context
10331048
stmt *driverStmt

0 commit comments

Comments
 (0)