mirror of
https://github.com/dolthub/dolt.git
synced 2025-12-16 20:25:20 -06:00
amend Dockerfile to embed interpreters from diff build stages
# Conflicts: # go/cmd/dolt/doltversion/version.go # go/go.mod # go/go.sum
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
**/.git
|
||||
**/.github
|
||||
**/docker/
|
||||
**/images/
|
||||
108
.github/actions/mysql-client-tests/Dockerfile
vendored
108
.github/actions/mysql-client-tests/Dockerfile
vendored
@@ -4,7 +4,6 @@ ENV CGO_ENABLED=1
|
||||
ENV GO_LDFLAGS="-linkmode external -extldflags '-static'"
|
||||
RUN apk add --no-cache build-base
|
||||
|
||||
|
||||
FROM golang_cgo125 AS dolt_build
|
||||
COPY dolt/go/go.mod /build/dolt/go/
|
||||
COPY go-mysql-server*/ /build/go-mysql-server/
|
||||
@@ -13,18 +12,16 @@ WORKDIR /build/dolt/go/
|
||||
RUN go mod download
|
||||
RUN apk add --no-cache icu-dev icu-static
|
||||
COPY dolt/go/ /build/dolt/go/
|
||||
RUN go build -tags icu_static -o /build/bin/dolt ./cmd/dolt
|
||||
|
||||
RUN go build -tags icu_static -ldflags "$GO_LDFLAGS" -o /build/bin/dolt ./cmd/dolt
|
||||
|
||||
FROM golang_cgo125 AS go_clients_build
|
||||
COPY dolt/integration-tests/mysql-client-tests/go /build/go/
|
||||
WORKDIR /build/go/
|
||||
RUN go build -o /build/bin/go-mysql-client-test
|
||||
RUN go build -ldflags "$GO_LDFLAGS" -o /build/bin/go-mysql-client-test
|
||||
|
||||
COPY dolt/integration-tests/mysql-client-tests/go-mysql/ /build/go-mysql/
|
||||
WORKDIR /build/go-mysql/
|
||||
RUN go build -o /build/bin/go-sql-driver-test
|
||||
|
||||
RUN go build -ldflags "$GO_LDFLAGS" -o /build/bin/go-sql-driver-test
|
||||
|
||||
FROM rust:1.90-alpine3.22 AS rust_clients_build
|
||||
COPY dolt/integration-tests/mysql-client-tests/rust/ /build/rust/
|
||||
@@ -32,7 +29,6 @@ WORKDIR /build/rust/
|
||||
RUN apk add --no-cache musl-dev
|
||||
RUN cargo build --release --target-dir /build/bin/ # exe is in release/
|
||||
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim AS dotnet_clients_build
|
||||
COPY dolt/integration-tests/mysql-client-tests/dotnet/MySqlClient/ /build/dotnet/MySqlClient/
|
||||
WORKDIR /build/dotnet/MySqlClient/
|
||||
@@ -42,19 +38,101 @@ COPY dolt/integration-tests/mysql-client-tests/dotnet/MySqlConnector/ /build/dot
|
||||
WORKDIR /build/dotnet/MySqlConnector/
|
||||
RUN dotnet publish -c Release -o /build/bin
|
||||
|
||||
|
||||
FROM mcr.microsoft.com/devcontainers/cpp:1-bookworm AS c_clients_build
|
||||
COPY dolt/integration-tests/mysql-client-tests/c/vcpkg.json /build/c/vcpkg.json
|
||||
WORKDIR /build/c/
|
||||
RUN vcpkg install --triplet=x64-linux-release
|
||||
FROM gcc:12.5-bookworm AS c_clients_build
|
||||
RUN apt-get update && apt-get install -y \
|
||||
default-libmysqlclient-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY dolt/integration-tests/mysql-client-tests/c/ /build/c/
|
||||
ENV CMAKE_TOOLCHAIN_FILE=/usr/local/vcpkg/scripts/buildsystems/vcpkg.cmake
|
||||
RUN cmake -B build -S .
|
||||
RUN cmake --build build
|
||||
WORKDIR /build/c/
|
||||
RUN make
|
||||
|
||||
FROM gcc:12.5-bookworm AS cpp_clients_build
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libmysqlcppconn-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
COPY dolt/integration-tests/mysql-client-tests/cpp/ /build/cpp/
|
||||
WORKDIR /build/cpp/
|
||||
RUN make
|
||||
|
||||
FROM python:3.14-slim-bookworm AS python_clients_build
|
||||
RUN apt-get update && apt-get install -y binutils && rm -rf /var/lib/apt/lists/*
|
||||
RUN pip install --no-cache-dir mysql-connector-python==8.0.33 PyMySQL==1.0.2 sqlalchemy==1.4.46 pyinstaller
|
||||
COPY dolt/integration-tests/mysql-client-tests/python/ /build/python/
|
||||
WORKDIR /build/python/
|
||||
RUN pyinstaller --onefile pymysql-test.py
|
||||
RUN pyinstaller --onefile --collect-all mysql.connector py-sqlalchemy-test.py
|
||||
RUN pyinstaller --onefile --collect-all mysql.connector py-mysql-connector-test.py
|
||||
|
||||
FROM elixir:1.18-slim AS elixir_clients_build
|
||||
RUN apt-get update && apt-get install -y ca-certificates xz-utils curl && rm -rf /var/lib/apt/lists/*
|
||||
RUN curl -sSL https://ziglang.org/download/0.14.1/zig-x86_64-linux-0.14.1.tar.xz | tar -xJ
|
||||
ENV PATH="/zig-x86_64-linux-0.14.1:${PATH}"
|
||||
COPY dolt/integration-tests/mysql-client-tests/elixir/mix.exs /build/elixir/
|
||||
WORKDIR /build/elixir/
|
||||
RUN mix local.hex --force && mix local.rebar --force
|
||||
RUN mix deps.get
|
||||
COPY dolt/integration-tests/mysql-client-tests/elixir/ /build/elixir/
|
||||
RUN MIX_ENV=prod mix release
|
||||
RUN mkdir -p /build/bin && cp burrito_out/simple_linux /build/bin/elixir-mysql-client-test
|
||||
|
||||
FROM maven:3.9.11-amazoncorretto-21-debian-bookworm AS java_clients_build
|
||||
RUN apt-get update && apt-get install -y binutils && rm -rf /var/lib/apt/lists/*
|
||||
COPY dolt/integration-tests/mysql-client-tests/java/ /build/java/
|
||||
WORKDIR /build/java/
|
||||
RUN mvn package
|
||||
RUN jlink \
|
||||
--add-modules java.base,java.sql,java.naming,java.xml,java.logging,java.management \
|
||||
--strip-debug \
|
||||
--no-man-pages \
|
||||
--no-header-files \
|
||||
--output /build/jre
|
||||
|
||||
FROM node:22-bookworm-slim AS node_clients_build
|
||||
COPY dolt/integration-tests/mysql-client-tests/node/package.json /build/bin/
|
||||
WORKDIR /build/bin/
|
||||
RUN npm install --omit=dev
|
||||
COPY dolt/integration-tests/mysql-client-tests/node/ /build/bin/
|
||||
|
||||
FROM php:8.3-bookworm AS php_clients_build
|
||||
RUN docker-php-ext-install mysqli pdo_mysql
|
||||
COPY dolt/integration-tests/mysql-client-tests/php/ /build/bin/
|
||||
|
||||
FROM ruby:3.4-bookworm AS ruby_clients_build
|
||||
RUN apt-get update && apt-get install -y default-libmysqlclient-dev && rm -rf /var/lib/apt/lists/*
|
||||
COPY dolt/integration-tests/mysql-client-tests/ruby/Gemfile /build/ruby/
|
||||
WORKDIR /build/ruby/
|
||||
RUN bundle install
|
||||
COPY dolt/integration-tests/mysql-client-tests/ruby/ /build/bin/
|
||||
|
||||
FROM php:8.3-bookworm AS runtime
|
||||
RUN apt-get update && apt-get install -y \
|
||||
default-libmysqlclient-dev \
|
||||
libmysqlcppconn-dev \
|
||||
r-base \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN R -e "install.packages(c('RMariaDB', 'RMySQL', 'DBI'), repos='https://cloud.r-project.org/')"
|
||||
|
||||
COPY --from=dolt_build /build/bin/ /usr/local/bin/
|
||||
COPY --from=go_clients_build /build/bin/ /build/bin/go/
|
||||
COPY --from=rust_clients_build /build/bin/release/ /build/bin/rust/
|
||||
COPY --from=dotnet_clients_build /build/bin/ /build/bin/dotnet/
|
||||
COPY --from=c_clients_build /build/bin/ /build/bin/c/
|
||||
COPY --from=cpp_clients_build /build/bin/ /build/bin/cpp/
|
||||
COPY --from=python_clients_build /build/python/dist/ /build/bin/python/
|
||||
COPY --from=elixir_clients_build /build/bin/ /build/bin/elixir/
|
||||
COPY --from=java_clients_build /build/java/target/ /build/bin/java/
|
||||
COPY --from=node_clients_build /build/bin/ /build/bin/node/
|
||||
COPY --from=php_clients_build /build/bin/ /build/bin/php/
|
||||
COPY --from=ruby_clients_build /build/bin/ /build/bin/ruby/
|
||||
COPY dolt/integration-tests/mysql-client-tests/r/ /build/bin/r/
|
||||
|
||||
COPY --from=java_clients_build /build/jre/ /opt/jre/
|
||||
COPY --from=node_clients_build /usr/local/bin/node /usr/local/bin/node
|
||||
COPY --from=php_clients_build /usr/local/lib/php/extensions/ /usr/local/lib/php/extensions/
|
||||
COPY --from=php_clients_build /usr/local/etc/php/conf.d/ /usr/local/etc/php/conf.d/
|
||||
COPY --from=ruby_clients_build /usr/local/bin/ruby /usr/local/bin/ruby
|
||||
COPY --from=ruby_clients_build /usr/local/lib/ /usr/local/lib/
|
||||
COPY --from=ruby_clients_build /usr/local/bundle/ /usr/local/bundle/
|
||||
ENV PATH="/opt/jre/bin:/usr/local/bundle/bin:${PATH}"
|
||||
ENV GEM_HOME="/usr/local/bundle"
|
||||
ENV BUNDLE_APP_CONFIG="/usr/local/bundle"
|
||||
|
||||
5
.github/actions/mysql-client-tests/Dockerfile.dockerignore
vendored
Normal file
5
.github/actions/mysql-client-tests/Dockerfile.dockerignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
**/.git/
|
||||
**/.github/
|
||||
**/docker/
|
||||
**/images/
|
||||
**/node_modules/
|
||||
@@ -1,5 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
project(c_mysql_client_test C)
|
||||
find_package(unofficial-libmysql REQUIRED)
|
||||
add_executable("c-mysql-client-test" "mysql-connector-c-test.c")
|
||||
target_link_libraries("c-mysql-client-test" PRIVATE unofficial::libmysql::libmysql stdc++)
|
||||
@@ -1,11 +1,18 @@
|
||||
CFLAGS := $(shell pkg-config --cflags mysqlclient)
|
||||
LDFLAGS := $(shell pkg-config --libs mysqlclient)
|
||||
CC = gcc
|
||||
|
||||
all: mysql-connector-c-test
|
||||
CFLAGS = -I/usr/include/mysql -Wall -O2
|
||||
|
||||
mysql-connector-c-test: mysql-connector-c-test.c
|
||||
LDFLAGS = -lmysqlclient
|
||||
|
||||
TARGET = /build/bin/c-mysql-client-test
|
||||
|
||||
SRCS = mysql-connector-c-test.c
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(SRCS)
|
||||
@mkdir -p /build/bin
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f mysql-connector-c-test
|
||||
rm -f /build/bin/c-mysql-client-test
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <mysql/mysql.h>
|
||||
#include <mysql.h>
|
||||
|
||||
#define QUERIES_SIZE 14
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"name": "mysql-client-test-c",
|
||||
"dependencies": [ "libmysql" ]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(DoltCxxConnectorTest
|
||||
VERSION 0.1
|
||||
DESCRIPTION "A smoke test for mysql-connector-c++ connecting to Dolt"
|
||||
LANGUAGES CXX)
|
||||
|
||||
add_executable(test_mysql_connector_cxx mysql-connector-cpp-test.cpp)
|
||||
set_property(TARGET test_mysql_connector_cxx PROPERTY CXX_STANDARD 11)
|
||||
|
||||
if(WITH_JDBC)
|
||||
add_subdirectory(third_party/mysql-connector-cpp EXCLUDE_FROM_ALL)
|
||||
target_link_libraries(test_mysql_connector_cxx connector-jdbc)
|
||||
else()
|
||||
find_library(LIBMYSQLCPPCONN "mysqlcppconn")
|
||||
target_link_libraries(test_mysql_connector_cxx "${LIBMYSQLCPPCONN}")
|
||||
endif()
|
||||
@@ -1,14 +1,14 @@
|
||||
MYSQL_CONCPP_DIR = /usr/local/Cellar/mysql-connector-c++/8.0.21
|
||||
CPPFLAGS = -I $(MYSQL_CONCPP_DIR)/include -L $(MYSQL_CONCPP_DIR)/lib64
|
||||
LDLIBS = -lmysqlcppconn8
|
||||
CXX = clang++ -stdlib=libc++
|
||||
CXXFLAGS = -std=c++11
|
||||
CXX = g++
|
||||
CXXFLAGS = -I/usr/include/cppconn -std=c++11 -Wall -O2
|
||||
LDFLAGS = -lmysqlcppconn
|
||||
TARGET = /build/bin/cpp-mysql-connector-test
|
||||
SRCS = mysql-connector-cpp-test.cpp
|
||||
|
||||
all: mysql-connector-cpp-test
|
||||
all: $(TARGET)
|
||||
|
||||
mysql-connector-cpp-test: mysql-connector-cpp-test.cpp
|
||||
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $@ $^ $(LDLIBS)
|
||||
$(TARGET): $(SRCS)
|
||||
@mkdir -p /build/bin
|
||||
$(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f mysql-connector-cpp-test
|
||||
rm -f $(TARGET)
|
||||
|
||||
@@ -46,6 +46,11 @@ std::string queries[QUERIES_SIZE] =
|
||||
int is_update[QUERIES_SIZE] = {1,0,0,1,0,0,0,0,0,1,0,0,0,0};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 4) {
|
||||
std::cerr << "Usage: " << argv[0] << " <user> <port> <database>" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string user = argv[1];
|
||||
std::string port = argv[2];
|
||||
std::string db = argv[3];
|
||||
|
||||
Submodule integration-tests/mysql-client-tests/cpp/third_party/mysql-connector-cpp deleted from 857a8d63d8
@@ -1,16 +1,26 @@
|
||||
defmodule SmokeTest do
|
||||
def myTestFunc(arg1, arg2) do
|
||||
if arg1 != arg2 do
|
||||
raise "Test error"
|
||||
end
|
||||
def main(_args \\ []) do
|
||||
IO.puts("Starting SmokeTest.main/1")
|
||||
|
||||
cli_args = Burrito.Util.Args.get_arguments()
|
||||
IO.puts("Received CLI args: #{inspect(cli_args)}")
|
||||
|
||||
result = run(cli_args)
|
||||
System.halt(0)
|
||||
result
|
||||
end
|
||||
|
||||
@spec run :: nil
|
||||
def run do
|
||||
args = System.argv()
|
||||
defp run(args) do
|
||||
if length(args) < 3 do
|
||||
IO.puts("Usage: simple <user> <port> <database>")
|
||||
System.halt(1)
|
||||
end
|
||||
|
||||
user = Enum.at(args, 0)
|
||||
{port, _} = Integer.parse(Enum.at(args, 1))
|
||||
port_str = Enum.at(args, 1)
|
||||
database = Enum.at(args, 2)
|
||||
|
||||
{port, _} = Integer.parse(port_str)
|
||||
|
||||
{:ok, pid} = MyXQL.start_link(username: user, port: port, database: database)
|
||||
{:ok, _} = MyXQL.query(pid, "drop table if exists test")
|
||||
@@ -21,8 +31,6 @@ defmodule SmokeTest do
|
||||
myTestFunc(result.num_rows, 0)
|
||||
|
||||
{:ok, _} = MyXQL.query(pid, "insert into test (pk, `value`) values (0,0)")
|
||||
|
||||
# MyXQL uses the CLIENT_FOUND_ROWS flag so we should return the number of rows matched
|
||||
{:ok, result} = MyXQL.query(pid, "UPDATE test SET pk = pk where pk = 0")
|
||||
myTestFunc(result.num_rows, 1)
|
||||
|
||||
@@ -31,7 +39,7 @@ defmodule SmokeTest do
|
||||
|
||||
{:ok, result} = MyXQL.query(pid, "SELECT * FROM test")
|
||||
myTestFunc(result.num_rows, 1)
|
||||
myTestFunc(result.rows, [[0,0]])
|
||||
myTestFunc(result.rows, [[0, 0]])
|
||||
|
||||
{:ok, _} = MyXQL.query(pid, "call dolt_add('-A');")
|
||||
{:ok, _} = MyXQL.query(pid, "call dolt_commit('-m', 'my commit')")
|
||||
@@ -45,5 +53,12 @@ defmodule SmokeTest do
|
||||
{:ok, result} = MyXQL.query(pid, "select COUNT(*) FROM dolt_log")
|
||||
myTestFunc(result.num_rows, 1)
|
||||
myTestFunc(result.rows, [[3]])
|
||||
:ok
|
||||
end
|
||||
|
||||
defp myTestFunc(arg1, arg2) do
|
||||
if arg1 != arg2 do
|
||||
raise "Test error: expected #{inspect(arg2)}, got #{inspect(arg1)}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,15 +5,38 @@ defmodule Simple.MixProject do
|
||||
[
|
||||
app: :simple,
|
||||
version: "0.1.0",
|
||||
elixir: "~> 1.18",
|
||||
start_permanent: Mix.env() == :prod,
|
||||
deps: deps()
|
||||
deps: deps(),
|
||||
releases: releases()
|
||||
]
|
||||
end
|
||||
|
||||
def application do
|
||||
[
|
||||
extra_applications: [:logger, :crypto, :public_key, :ssl],
|
||||
mod: {Simple.Application, []}
|
||||
]
|
||||
end
|
||||
|
||||
defp releases do
|
||||
[
|
||||
simple: [
|
||||
steps: [:assemble, &Burrito.wrap/1],
|
||||
burrito: [
|
||||
targets: [
|
||||
linux: [os: :linux, cpu: :x86_64]
|
||||
],
|
||||
no_native_archivers: true
|
||||
]
|
||||
]
|
||||
]
|
||||
end
|
||||
|
||||
# Run "mix help deps" to learn about dependencies.
|
||||
defp deps do
|
||||
[
|
||||
{:myxql, "~> 0.5.0"},
|
||||
{:burrito, "~> 1.4.0"}
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,173 +1,173 @@
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
|
||||
public class MySQLConnectorTest {
|
||||
|
||||
// test queries to be run against Dolt
|
||||
private static final String[] queries = {
|
||||
"create table test (pk int, `value` int, primary key(pk))",
|
||||
"describe test",
|
||||
"select * from test",
|
||||
"insert into test (pk, `value`) values (0,0)",
|
||||
"select * from test",
|
||||
"call dolt_add('-A')",
|
||||
"call dolt_commit('-m', 'my commit')",
|
||||
"select COUNT(*) FROM dolt_log",
|
||||
"call dolt_checkout('-b', 'mybranch')",
|
||||
"insert into test (pk, `value`) values (1,1)",
|
||||
"call dolt_commit('-a', '-m', 'my commit2')",
|
||||
"call dolt_checkout('main')",
|
||||
"call dolt_merge('mybranch')",
|
||||
"select COUNT(*) FROM dolt_log",
|
||||
};
|
||||
|
||||
// We currently only test a single field value in the first row
|
||||
private static final String[] expectedResults = {
|
||||
"0",
|
||||
"pk",
|
||||
null,
|
||||
"1",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"2",
|
||||
"0",
|
||||
"1",
|
||||
"1",
|
||||
"0",
|
||||
"",
|
||||
"3"
|
||||
};
|
||||
|
||||
// fieldAccessors are the value used to access a field in a row in a result set. Currently, only
|
||||
// String (i.e column name) and Integer (i.e. field position) values are supported.
|
||||
private static final Object[] fieldAccessors = {
|
||||
1,
|
||||
1,
|
||||
"pk",
|
||||
1,
|
||||
"test.pk",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
"COUNT(*)",
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
testStatements(args);
|
||||
testServerSideCursors(args);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// testServerSideCursors does a simple smoke test with server-side cursors to make sure
|
||||
// results can be read. Note that we don't test results here; this is just a high level
|
||||
// smoke test that we can execute server-side cursors logic without the server erroring out.
|
||||
// This test was added for a regression where server-side cursor logic was getting
|
||||
// corrupted result set memory and sending invalid data to the client, which caused the
|
||||
// server to error out and crash the connection. If any errors are encountered, a stack trace
|
||||
// is printed and this function exits with a non-zero code.
|
||||
// For more details, see: https://github.com/dolthub/dolt/issues/9125
|
||||
private static void testServerSideCursors(String[] args) {
|
||||
String user = args[0];
|
||||
String port = args[1];
|
||||
String db = args[2];
|
||||
|
||||
try {
|
||||
String url = "jdbc:mysql://127.0.0.1:" + port + "/" + db +
|
||||
"?useServerPrepStmts=true&useCursorFetch=true";
|
||||
Connection conn = DriverManager.getConnection(url, user, "");
|
||||
|
||||
executePreparedQuery(conn, "SELECT 1;");
|
||||
executePreparedQuery(conn, "SELECT database();");
|
||||
executePreparedQuery(conn, "SHOW COLLATION;");
|
||||
executePreparedQuery(conn, "SHOW COLLATION;");
|
||||
executePreparedQuery(conn, "SHOW COLLATION;");
|
||||
} catch (SQLException ex) {
|
||||
System.out.println("An error occurred.");
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// executePreparedQuery executes the specified |query| using |conn| as a prepared statement,
|
||||
// and uses server-side cursor to fetch results. This method does not do any validation of
|
||||
// results from the query. It is simply a smoke test to ensure the connection doesn't crash.
|
||||
private static void executePreparedQuery(Connection conn, String query) throws SQLException {
|
||||
PreparedStatement stmt = conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY);
|
||||
stmt.setFetchSize(25); // needed to ensure a server-side cursor is used
|
||||
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
while (rs.next()) {}
|
||||
|
||||
rs.close();
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
// testStatements executes the queries from |queries| and asserts their results from
|
||||
// |expectedResults|. If any errors are encountered, a stack trace is printed and this
|
||||
// function exits with a non-zero code.
|
||||
private static void testStatements(String[] args) {
|
||||
Connection conn = null;
|
||||
|
||||
String user = args[0];
|
||||
String port = args[1];
|
||||
String db = args[2];
|
||||
|
||||
try {
|
||||
String url = "jdbc:mysql://127.0.0.1:" + port + "/" + db;
|
||||
String password = "";
|
||||
|
||||
conn = DriverManager.getConnection(url, user, password);
|
||||
Statement st = conn.createStatement();
|
||||
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
String query = queries[i];
|
||||
String expected = expectedResults[i];
|
||||
if ( st.execute(query) ) {
|
||||
ResultSet rs = st.getResultSet();
|
||||
if (rs.next()) {
|
||||
String result = "";
|
||||
Object fieldAccessor = fieldAccessors[i];
|
||||
if (fieldAccessor instanceof String) {
|
||||
result = rs.getString((String)fieldAccessor);
|
||||
} else if (fieldAccessor instanceof Integer) {
|
||||
result = rs.getString((Integer)fieldAccessor);
|
||||
} else {
|
||||
System.out.println("Unsupported field accessor value: " + fieldAccessor);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if (!expected.equals(result) && !(query.contains("dolt_commit")) && !(query.contains("dolt_merge"))) {
|
||||
System.out.println("Query: \n" + query);
|
||||
System.out.println("Expected:\n" + expected);
|
||||
System.out.println("Result:\n" + result);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String result = Integer.toString(st.getUpdateCount());
|
||||
if ( !expected.equals(result) ) {
|
||||
System.out.println("Query: \n" + query);
|
||||
System.out.println("Expected:\n" + expected);
|
||||
System.out.println("Rows Updated:\n" + result);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
System.out.println("An error occurred.");
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
|
||||
public class MySQLConnectorTest {
|
||||
|
||||
// test queries to be run against Dolt
|
||||
private static final String[] queries = {
|
||||
"create table test (pk int, `value` int, primary key(pk))",
|
||||
"describe test",
|
||||
"select * from test",
|
||||
"insert into test (pk, `value`) values (0,0)",
|
||||
"select * from test",
|
||||
"call dolt_add('-A')",
|
||||
"call dolt_commit('-m', 'my commit')",
|
||||
"select COUNT(*) FROM dolt_log",
|
||||
"call dolt_checkout('-b', 'mybranch')",
|
||||
"insert into test (pk, `value`) values (1,1)",
|
||||
"call dolt_commit('-a', '-m', 'my commit2')",
|
||||
"call dolt_checkout('main')",
|
||||
"call dolt_merge('mybranch')",
|
||||
"select COUNT(*) FROM dolt_log",
|
||||
};
|
||||
|
||||
// We currently only test a single field value in the first row
|
||||
private static final String[] expectedResults = {
|
||||
"0",
|
||||
"pk",
|
||||
null,
|
||||
"1",
|
||||
"0",
|
||||
"0",
|
||||
"0",
|
||||
"2",
|
||||
"0",
|
||||
"1",
|
||||
"1",
|
||||
"0",
|
||||
"",
|
||||
"3"
|
||||
};
|
||||
|
||||
// fieldAccessors are the value used to access a field in a row in a result set. Currently, only
|
||||
// String (i.e column name) and Integer (i.e. field position) values are supported.
|
||||
private static final Object[] fieldAccessors = {
|
||||
1,
|
||||
1,
|
||||
"pk",
|
||||
1,
|
||||
"test.pk",
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
"COUNT(*)",
|
||||
};
|
||||
|
||||
public static void main(String[] args) {
|
||||
testStatements(args);
|
||||
testServerSideCursors(args);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// testServerSideCursors does a simple smoke test with server-side cursors to make sure
|
||||
// results can be read. Note that we don't test results here; this is just a high level
|
||||
// smoke test that we can execute server-side cursors logic without the server erroring out.
|
||||
// This test was added for a regression where server-side cursor logic was getting
|
||||
// corrupted result set memory and sending invalid data to the client, which caused the
|
||||
// server to error out and crash the connection. If any errors are encountered, a stack trace
|
||||
// is printed and this function exits with a non-zero code.
|
||||
// For more details, see: https://github.com/dolthub/dolt/issues/9125
|
||||
private static void testServerSideCursors(String[] args) {
|
||||
String user = args[0];
|
||||
String port = args[1];
|
||||
String db = args[2];
|
||||
|
||||
try {
|
||||
String url = "jdbc:mysql://127.0.0.1:" + port + "/" + db +
|
||||
"?useServerPrepStmts=true&useCursorFetch=true";
|
||||
Connection conn = DriverManager.getConnection(url, user, "");
|
||||
|
||||
executePreparedQuery(conn, "SELECT 1;");
|
||||
executePreparedQuery(conn, "SELECT database();");
|
||||
executePreparedQuery(conn, "SHOW COLLATION;");
|
||||
executePreparedQuery(conn, "SHOW COLLATION;");
|
||||
executePreparedQuery(conn, "SHOW COLLATION;");
|
||||
} catch (SQLException ex) {
|
||||
System.out.println("An error occurred.");
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// executePreparedQuery executes the specified |query| using |conn| as a prepared statement,
|
||||
// and uses server-side cursor to fetch results. This method does not do any validation of
|
||||
// results from the query. It is simply a smoke test to ensure the connection doesn't crash.
|
||||
private static void executePreparedQuery(Connection conn, String query) throws SQLException {
|
||||
PreparedStatement stmt = conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY);
|
||||
stmt.setFetchSize(25); // needed to ensure a server-side cursor is used
|
||||
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
while (rs.next()) {}
|
||||
|
||||
rs.close();
|
||||
stmt.close();
|
||||
}
|
||||
|
||||
// testStatements executes the queries from |queries| and asserts their results from
|
||||
// |expectedResults|. If any errors are encountered, a stack trace is printed and this
|
||||
// function exits with a non-zero code.
|
||||
private static void testStatements(String[] args) {
|
||||
Connection conn = null;
|
||||
|
||||
String user = args[0];
|
||||
String port = args[1];
|
||||
String db = args[2];
|
||||
|
||||
try {
|
||||
String url = "jdbc:mysql://127.0.0.1:" + port + "/" + db;
|
||||
String password = "";
|
||||
|
||||
conn = DriverManager.getConnection(url, user, password);
|
||||
Statement st = conn.createStatement();
|
||||
|
||||
for (int i = 0; i < queries.length; i++) {
|
||||
String query = queries[i];
|
||||
String expected = expectedResults[i];
|
||||
if ( st.execute(query) ) {
|
||||
ResultSet rs = st.getResultSet();
|
||||
if (rs.next()) {
|
||||
String result = "";
|
||||
Object fieldAccessor = fieldAccessors[i];
|
||||
if (fieldAccessor instanceof String) {
|
||||
result = rs.getString((String)fieldAccessor);
|
||||
} else if (fieldAccessor instanceof Integer) {
|
||||
result = rs.getString((Integer)fieldAccessor);
|
||||
} else {
|
||||
System.out.println("Unsupported field accessor value: " + fieldAccessor);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
if (!expected.equals(result) && !(query.contains("dolt_commit")) && !(query.contains("dolt_merge"))) {
|
||||
System.out.println("Query: \n" + query);
|
||||
System.out.println("Expected:\n" + expected);
|
||||
System.out.println("Result:\n" + result);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String result = Integer.toString(st.getUpdateCount());
|
||||
if ( !expected.equals(result) ) {
|
||||
System.out.println("Query: \n" + query);
|
||||
System.out.println("Expected:\n" + expected);
|
||||
System.out.println("Rows Updated:\n" + result);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SQLException ex) {
|
||||
System.out.println("An error occurred.");
|
||||
ex.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,70 +1,70 @@
|
||||
import mysql.connector
|
||||
import sys
|
||||
|
||||
QUERY_RESPONSE = [
|
||||
{"create table test (pk int, `value` int, primary key(pk))": []},
|
||||
{"describe test": [
|
||||
('pk', 'int', 'NO', 'PRI', None, ''),
|
||||
('value', 'int', 'YES', '', None, '')
|
||||
]},
|
||||
{"insert into test (pk, `value`) values (0,0)": []},
|
||||
{"select * from test": [(0, 0)]},
|
||||
# We used to have a bug where spaces after a semicolon in a query
|
||||
# would cause a client/server disconnect.
|
||||
# https://github.com/dolthub/vitess/pull/65
|
||||
# The following regression tests it.
|
||||
{"select * from test; ": [(0, 0)]},
|
||||
{"select * from test; ": [(0, 0)]},
|
||||
# Test the Dolt SQL functions
|
||||
{"call dolt_add('-A');": [(0,)]},
|
||||
{"call dolt_commit('-m', 'my commit')": [('',)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(2,)]},
|
||||
{"call dolt_checkout('-b', 'mybranch')": [(0, "Switched to branch 'mybranch'")]},
|
||||
{"insert into test (pk, `value`) values (1,1)": []},
|
||||
{"call dolt_commit('-a', '-m', 'my commit2')": [('',)]},
|
||||
{"call dolt_checkout('main')": [(0, "Switched to branch 'main'")]},
|
||||
{"call dolt_merge('mybranch')": [('',1,0,)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(3,)]},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
user = sys.argv[1]
|
||||
port = sys.argv[2]
|
||||
db = sys.argv[3]
|
||||
|
||||
connection = mysql.connector.connect(user=user,
|
||||
host="127.0.0.1",
|
||||
port=port,
|
||||
database=db)
|
||||
|
||||
for query_response in QUERY_RESPONSE:
|
||||
query = list(query_response.keys())[0]
|
||||
exp_results = query_response[query]
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
try:
|
||||
results = cursor.fetchall()
|
||||
print(exp_results)
|
||||
print(results)
|
||||
if (results != exp_results) and ("dolt_commit" not in query) and ("dolt_merge" not in query):
|
||||
print("Query:")
|
||||
print(query)
|
||||
print("Expected:")
|
||||
print(exp_results)
|
||||
print("Received:")
|
||||
print(results)
|
||||
exit(1)
|
||||
except mysql.connector.errors.InterfaceError:
|
||||
|
||||
# This is a write query
|
||||
pass
|
||||
|
||||
cursor.close()
|
||||
|
||||
connection.close()
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
main()
|
||||
import mysql.connector
|
||||
import sys
|
||||
|
||||
QUERY_RESPONSE = [
|
||||
{"create table test (pk int, `value` int, primary key(pk))": []},
|
||||
{"describe test": [
|
||||
('pk', 'int', 'NO', 'PRI', None, ''),
|
||||
('value', 'int', 'YES', '', None, '')
|
||||
]},
|
||||
{"insert into test (pk, `value`) values (0,0)": []},
|
||||
{"select * from test": [(0, 0)]},
|
||||
# We used to have a bug where spaces after a semicolon in a query
|
||||
# would cause a client/server disconnect.
|
||||
# https://github.com/dolthub/vitess/pull/65
|
||||
# The following regression tests it.
|
||||
{"select * from test; ": [(0, 0)]},
|
||||
{"select * from test; ": [(0, 0)]},
|
||||
# Test the Dolt SQL functions
|
||||
{"call dolt_add('-A');": [(0,)]},
|
||||
{"call dolt_commit('-m', 'my commit')": [('',)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(2,)]},
|
||||
{"call dolt_checkout('-b', 'mybranch')": [(0, "Switched to branch 'mybranch'")]},
|
||||
{"insert into test (pk, `value`) values (1,1)": []},
|
||||
{"call dolt_commit('-a', '-m', 'my commit2')": [('',)]},
|
||||
{"call dolt_checkout('main')": [(0, "Switched to branch 'main'")]},
|
||||
{"call dolt_merge('mybranch')": [('',1,0,)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(3,)]},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
user = sys.argv[1]
|
||||
port = sys.argv[2]
|
||||
db = sys.argv[3]
|
||||
|
||||
connection = mysql.connector.connect(user=user,
|
||||
host="127.0.0.1",
|
||||
port=port,
|
||||
database=db)
|
||||
|
||||
for query_response in QUERY_RESPONSE:
|
||||
query = list(query_response.keys())[0]
|
||||
exp_results = query_response[query]
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(query)
|
||||
try:
|
||||
results = cursor.fetchall()
|
||||
print(exp_results)
|
||||
print(results)
|
||||
if (results != exp_results) and ("dolt_commit" not in query) and ("dolt_merge" not in query):
|
||||
print("Query:")
|
||||
print(query)
|
||||
print("Expected:")
|
||||
print(exp_results)
|
||||
print("Received:")
|
||||
print(results)
|
||||
exit(1)
|
||||
except mysql.connector.errors.InterfaceError:
|
||||
|
||||
# This is a write query
|
||||
pass
|
||||
|
||||
cursor.close()
|
||||
|
||||
connection.close()
|
||||
|
||||
exit(0)
|
||||
|
||||
|
||||
main()
|
||||
@@ -1,67 +1,67 @@
|
||||
import sqlalchemy
|
||||
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import sys
|
||||
|
||||
QUERY_RESPONSE = [
|
||||
{"create table test (pk int, `value` int, primary key(pk))": []},
|
||||
{"describe test": [
|
||||
('pk', 'int', 'NO', 'PRI', None, ''),
|
||||
('value', 'int', 'YES', '', None, '')
|
||||
]},
|
||||
{"insert into test (pk, `value`) values (0,0)": ()},
|
||||
{"select * from test": [(0, 0)]},
|
||||
{"call dolt_add('-A');": [(0,)]},
|
||||
{"call dolt_commit('-m', 'my commit')": [('',)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(2,)]},
|
||||
{"call dolt_checkout('-b', 'mybranch')": [(0, "Switched to branch 'mybranch'")]},
|
||||
{"insert into test (pk, `value`) values (1,1)": []},
|
||||
{"call dolt_commit('-a', '-m', 'my commit2')": [('',)]},
|
||||
{"call dolt_checkout('main')": [(0, "Switched to branch 'main'")]},
|
||||
{"call dolt_merge('mybranch')": [('',1,0,)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(3,)]},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
user = sys.argv[1]
|
||||
port = int(sys.argv[2])
|
||||
db = sys.argv[3]
|
||||
|
||||
conn_string_base = "mysql+mysqlconnector://"
|
||||
|
||||
engine = create_engine(conn_string_base +
|
||||
"{user}@127.0.0.1:{port}/{db}".format(user=user,
|
||||
port=port,
|
||||
db=db)
|
||||
)
|
||||
|
||||
with engine.connect() as con:
|
||||
for query_response in QUERY_RESPONSE:
|
||||
query = list(query_response.keys())[0]
|
||||
exp_results = query_response[query]
|
||||
|
||||
result_proxy = con.execute(query)
|
||||
|
||||
try:
|
||||
results = result_proxy.fetchall()
|
||||
if (results != exp_results) and ("dolt_commit" not in query) and ("dolt_merge" not in query):
|
||||
print("Query:")
|
||||
print(query)
|
||||
print("Expected:")
|
||||
print(exp_results)
|
||||
print("Received:")
|
||||
print(results)
|
||||
exit(1)
|
||||
# You can't call fetchall on an insert
|
||||
# so we'll just ignore the exception
|
||||
except sqlalchemy.exc.ResourceClosedError:
|
||||
pass
|
||||
|
||||
con.close()
|
||||
exit(0)
|
||||
|
||||
|
||||
main()
|
||||
import sqlalchemy
|
||||
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
import sys
|
||||
|
||||
QUERY_RESPONSE = [
|
||||
{"create table test (pk int, `value` int, primary key(pk))": []},
|
||||
{"describe test": [
|
||||
('pk', 'int', 'NO', 'PRI', None, ''),
|
||||
('value', 'int', 'YES', '', None, '')
|
||||
]},
|
||||
{"insert into test (pk, `value`) values (0,0)": ()},
|
||||
{"select * from test": [(0, 0)]},
|
||||
{"call dolt_add('-A');": [(0,)]},
|
||||
{"call dolt_commit('-m', 'my commit')": [('',)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(2,)]},
|
||||
{"call dolt_checkout('-b', 'mybranch')": [(0, "Switched to branch 'mybranch'")]},
|
||||
{"insert into test (pk, `value`) values (1,1)": []},
|
||||
{"call dolt_commit('-a', '-m', 'my commit2')": [('',)]},
|
||||
{"call dolt_checkout('main')": [(0, "Switched to branch 'main'")]},
|
||||
{"call dolt_merge('mybranch')": [('',1,0,)]},
|
||||
{"select COUNT(*) FROM dolt_log": [(3,)]},
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
user = sys.argv[1]
|
||||
port = int(sys.argv[2])
|
||||
db = sys.argv[3]
|
||||
|
||||
conn_string_base = "mysql+mysqlconnector://"
|
||||
|
||||
engine = create_engine(conn_string_base +
|
||||
"{user}@127.0.0.1:{port}/{db}".format(user=user,
|
||||
port=port,
|
||||
db=db)
|
||||
)
|
||||
|
||||
with engine.connect() as con:
|
||||
for query_response in QUERY_RESPONSE:
|
||||
query = list(query_response.keys())[0]
|
||||
exp_results = query_response[query]
|
||||
|
||||
result_proxy = con.execute(query)
|
||||
|
||||
try:
|
||||
results = result_proxy.fetchall()
|
||||
if (results != exp_results) and ("dolt_commit" not in query) and ("dolt_merge" not in query):
|
||||
print("Query:")
|
||||
print(query)
|
||||
print("Expected:")
|
||||
print(exp_results)
|
||||
print("Received:")
|
||||
print(results)
|
||||
exit(1)
|
||||
# You can't call fetchall on an insert
|
||||
# so we'll just ignore the exception
|
||||
except sqlalchemy.exc.ResourceClosedError:
|
||||
pass
|
||||
|
||||
con.close()
|
||||
exit(0)
|
||||
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user