public CompletableFuture<InsertResponse> insert(String tableName,
                                     List<String> columnNames,
                                     DataStreamWriter writer,
                                     ClickHouseFormat format,
                                     InsertSettings settings) {

        String operationId = settings.getOperationId();
        ClientStatisticsHolder clientStats = null;
        if (operationId != null) {
            clientStats = globalClientStats.remove(operationId);
        }

        if (clientStats == null) {
            clientStats = new ClientStatisticsHolder();
        }
        clientStats.start(ClientMetrics.OP_DURATION);
        final ClientStatisticsHolder finalClientStats = clientStats;

        Supplier<InsertResponse> responseSupplier;


        final int writeBufferSize = settings.getInputStreamCopyBufferSize() <= 0 ?
                Integer.parseInt(configuration.getOrDefault(ClientConfigProperties.CLIENT_NETWORK_BUFFER_SIZE.getKey(), "8192")) :
                settings.getInputStreamCopyBufferSize();

        if (writeBufferSize <= 0) {
            throw new IllegalArgumentException("Buffer size must be greater than 0");
        }

        settings.setOption(ClientConfigProperties.INPUT_OUTPUT_FORMAT.getKey(), format.name());
        final InsertSettings finalSettings = settings;

        StringBuilder sqlStmt = new StringBuilder("INSERT INTO ").append(tableName);
        if (columnNames != null && !columnNames.isEmpty()) {
            sqlStmt.append(" (");
            for (String columnName : columnNames) {
                sqlStmt.append(columnName).append(", ");
            }
            sqlStmt.deleteCharAt(sqlStmt.length() - 2);
            sqlStmt.append(")");
        }
        sqlStmt.append(" FORMAT ").append(format.name());
        finalSettings.serverSetting(ClickHouseHttpProto.QPARAM_QUERY_STMT, sqlStmt.toString());
        responseSupplier = () -> {
            long startTime = System.nanoTime();
            // Selecting some node
            Endpoint selectedEndpoint = getNextAliveNode();

            RuntimeException lastException = null;
            for (int i = 0; i <= retries; i++) {
                // Execute request
                try (ClassicHttpResponse httpResponse =
                             httpClientHelper.executeRequest(selectedEndpoint, finalSettings.getAllSettings(), lz4Factory,
                                     out -> {
                                         writer.onOutput(out);
                                         out.close();
                                     })) {


                    // Check response
                    if (httpResponse.getCode() == HttpStatus.SC_SERVICE_UNAVAILABLE) {
                        LOG.warn("Failed to get response. Server returned {}. Retrying. (Duration: {})", System.nanoTime() - startTime, httpResponse.getCode());
                        selectedEndpoint = getNextAliveNode();
                        continue;
                    }

                    OperationMetrics metrics = new OperationMetrics(finalClientStats);
                    String summary = HttpAPIClientHelper.getHeaderVal(httpResponse.getFirstHeader(ClickHouseHttpProto.HEADER_SRV_SUMMARY), "{}");
                    ProcessParser.parseSummary(summary, metrics);
                    String queryId =  HttpAPIClientHelper.getHeaderVal(httpResponse.getFirstHeader(ClickHouseHttpProto.HEADER_QUERY_ID), finalSettings.getQueryId(), String::valueOf);
                    metrics.operationComplete();
                    metrics.setQueryId(queryId);
                    return new InsertResponse(metrics);
                } catch (Exception e) {
                    lastException = httpClientHelper.wrapException(String.format("Insert failed (Attempt: %s/%s - Duration: %s)",
                            (i + 1), (retries + 1), System.nanoTime() - startTime), e);
                    if (httpClientHelper.shouldRetry(e, finalSettings.getAllSettings())) {
                        LOG.warn("Retrying.", e);
                        selectedEndpoint = getNextAliveNode();
                    } else {
                        throw lastException;
                    }
                }

                if (i < retries) {
                    try {
                        writer.onRetry();
                    } catch (IOException ioe) {
                        throw new ClientException("Failed to reset stream before next attempt", ioe);
                    }
                }
            }
            throw new ClientException("Insert request failed after attempts: " + (retries + 1) + " - Duration: " + (System.nanoTime() - startTime), lastException);
        };

        return runAsyncOperation(responseSupplier, settings.getAllSettings());
    }
Does an insert request to a server. Data is pushed when a {@link DataStreamWriter#onOutput(OutputStream)} is called.

@param tableName - target table name
@param columnNames - list of column names to insert data into. If null or empty, all columns will be used.
@param writer - {@link DataStreamWriter} implementation
@param format - source format
@param settings - operation settings
@return {@code CompletableFuture<InsertResponse>} - a promise to insert response
client-v2/src/main/java/com/clickhouse/client/api/Client.java