001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.db.driver; 017 018import com.github.housepower.jdbc.ClickHouseConnection; 019import com.github.housepower.jdbc.connect.NativeClient; 020import com.github.housepower.jdbc.connect.NativeContext; 021import com.github.housepower.jdbc.misc.Validate; 022import com.github.housepower.jdbc.protocol.HelloResponse; 023import com.github.housepower.jdbc.protocol.QueryRequest; 024import com.github.housepower.jdbc.settings.ClickHouseConfig; 025import com.github.housepower.jdbc.settings.ClickHouseDefines; 026 027import java.net.InetSocketAddress; 028import java.sql.PreparedStatement; 029import java.sql.SQLException; 030import java.time.ZoneId; 031import java.util.Locale; 032 033public class NativeClickHouseConnection extends ClickHouseConnection { 034 035 protected NativeClickHouseConnection(ClickHouseConfig cfg, NativeContext nativeCtx) { 036 super(cfg, nativeCtx); 037 } 038 039 040 041 @Override 042 public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { 043// clickhouse 不支持 autoGeneratedKeys,但是 jfinal 调用了此方法会出错 044 return prepareStatement(sql); 045 } 046 047 048 public static ClickHouseConnection createClickHouseConnection(ClickHouseConfig configure) throws SQLException { 049 return new NativeClickHouseConnection(configure, createNativeContext(configure)); 050 } 051 052 private static NativeContext createNativeContext(ClickHouseConfig configure) throws SQLException { 053 NativeClient nativeClient = NativeClient.connect(configure); 054 return new NativeContext(clientContext(nativeClient, configure), serverContext(nativeClient, configure), nativeClient); 055 } 056 057 private static QueryRequest.ClientContext clientContext(NativeClient nativeClient, ClickHouseConfig configure) throws SQLException { 058 Validate.isTrue(nativeClient.address() instanceof InetSocketAddress); 059 InetSocketAddress address = (InetSocketAddress) nativeClient.address(); 060 String clientName = String.format(Locale.ROOT, "%s %s", ClickHouseDefines.NAME, "client"); 061 String initialAddress = "[::ffff:127.0.0.1]:0"; 062 return new QueryRequest.ClientContext(initialAddress, address.getHostName(), clientName); 063 } 064 065 private static NativeContext.ServerContext serverContext(NativeClient nativeClient, ClickHouseConfig configure) throws SQLException { 066 try { 067 long revision = ClickHouseDefines.CLIENT_REVISION; 068 nativeClient.sendHello("client", revision, configure.database(), configure.user(), configure.password()); 069 070 HelloResponse response = nativeClient.receiveHello(configure.queryTimeout(), null); 071 ZoneId timeZone = ZoneId.of(response.serverTimeZone()); 072 return new NativeContext.ServerContext( 073 response.majorVersion(), response.minorVersion(), response.reversion(), 074 configure, timeZone, response.serverDisplayName()); 075 } catch (SQLException rethrows) { 076 nativeClient.silentDisconnect(); 077 throw rethrows; 078 } 079 } 080 081}