11package com .clickhouse .jdbc ;
22
3+ import com .clickhouse .client .api .metadata .TableSchema ;
34import com .clickhouse .data .Tuple ;
45import com .clickhouse .jdbc .internal .ExceptionUtils ;
6+ import com .clickhouse .jdbc .internal .JdbcUtils ;
7+ import com .clickhouse .jdbc .metadata .ParameterMetaDataImpl ;
8+ import com .clickhouse .jdbc .metadata .ResultSetMetaDataImpl ;
59import org .slf4j .Logger ;
610import org .slf4j .LoggerFactory ;
711
3943import java .time .format .DateTimeFormatter ;
4044import java .time .format .DateTimeFormatterBuilder ;
4145import java .time .temporal .ChronoField ;
42- import java .util .ArrayList ;
43- import java .util .Calendar ;
44- import java .util .Collection ;
45- import java .util .GregorianCalendar ;
46- import java .util .List ;
47- import java .util .Map ;
46+ import java .util .*;
4847
4948public class PreparedStatementImpl extends StatementImpl implements PreparedStatement , JdbcV2Wrapper {
5049 private static final Logger LOG = LoggerFactory .getLogger (PreparedStatementImpl .class );
@@ -64,6 +63,11 @@ public class PreparedStatementImpl extends StatementImpl implements PreparedStat
6463 String insertIntoSQL ;
6564
6665 StatementType statementType ;
66+
67+ private final ParameterMetaData parameterMetaData ;
68+
69+ private ResultSetMetaData resultSetMetaData = null ;
70+
6771 public PreparedStatementImpl (ConnectionImpl connection , String sql ) throws SQLException {
6872 super (connection );
6973 this .originalSql = sql .trim ();
@@ -83,7 +87,7 @@ public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLEx
8387 } else {
8488 this .parameters = new Object [0 ];
8589 }
86-
90+ this . parameterMetaData = new ParameterMetaDataImpl ( this . parameters . length );
8791 this .defaultCalendar = connection .defaultCalendar ;
8892 }
8993
@@ -305,7 +309,30 @@ public void setArray(int parameterIndex, Array x) throws SQLException {
305309 @ Override
306310 public ResultSetMetaData getMetaData () throws SQLException {
307311 checkClosed ();
308- return null ;
312+
313+ if (resultSetMetaData == null && currentResultSet == null ) {
314+ // before execution
315+ if (statementType == StatementType .SELECT ) {
316+ try {
317+ String sql = JdbcUtils .replaceQuestionMarks (originalSql , JdbcUtils .NULL );
318+ TableSchema tSchema = connection .getClient ().getTableSchemaFromQuery (sql );
319+ resultSetMetaData = new ResultSetMetaDataImpl (tSchema .getColumns (),
320+ tSchema .getDatabaseName (), "" , tSchema .getTableName (), Collections .emptyMap ());
321+ } catch (Exception e ) {
322+ // fallback to empty until
323+ }
324+ } else if (statementType == StatementType .SHOW ) {
325+ // predefined
326+ } else if (statementType == StatementType .DESCRIBE ) {
327+ // predefined
328+ } else {
329+ // fallback to empty
330+ }
331+ } else if (resultSetMetaData == null ) {
332+ resultSetMetaData = currentResultSet .getMetaData ();
333+ }
334+
335+ return resultSetMetaData ;
309336 }
310337
311338 @ Override
@@ -352,10 +379,19 @@ public void setURL(int parameterIndex, URL x) throws SQLException {
352379 parameters [parameterIndex - 1 ] = encodeObject (x );
353380 }
354381
382+ /**
383+ * Current JDBC driver implementation implement this functionality.
384+ * But specification doesn't expect throwing an exception what
385+ * for makes us return a "dummy" object. Returned metadata reflects only
386+ * information we can guarantee like parameter count.
387+ * @see ParameterMetaDataImpl
388+ * @return {@link ParameterMetaDataImpl}
389+ * @throws SQLException if the statement is close
390+ */
355391 @ Override
356392 public ParameterMetaData getParameterMetaData () throws SQLException {
357393 checkClosed ();
358- return null ;
394+ return parameterMetaData ;
359395 }
360396
361397 @ Override
0 commit comments