All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ecwid.clickhouse.raw.RawResponse.kt Maven / Gradle / Ivy

package com.ecwid.clickhouse.raw

import com.ecwid.clickhouse.ClickHouseResponse
import com.ecwid.clickhouse.Meta
import com.ecwid.clickhouse.Statistics
import com.ecwid.clickhouse.transport.HttpResponse
import com.google.gson.stream.JsonReader

internal class RawResponse(private val httpResponse: HttpResponse) : ClickHouseResponse {

	private val jsonReader = JsonReader(httpResponse.content.asReader())
	private var iterationState = IterationState.BEFORE_ITERATION

	private val meta: Meta
	private var statistic: Statistics? = null
	private var rows: Long? = null
	private var rowsBeforeLimitAtLeast: Long? = null

	init {
		// start first iteration
		jsonReader.beginObject()

		// meta
		val metaKey = jsonReader.nextName()
		check(metaKey == "meta") {
			"'meta' object not found"
		}
		this.meta = readMetaObject(jsonReader)

		// open 'data' section in json
		val dataKey = jsonReader.nextName()
		check(dataKey == "data") {
			"'data' object not found"
		}
		jsonReader.beginArray()
		iterationState = IterationState.READY_TO_ITERATION
	}

	override fun iterator(): Iterator {
		check(iterationState == IterationState.READY_TO_ITERATION) {
			"You can iterate over ClickHouse response only once."
		}

		return RawIterator(jsonReader, this)
	}

	override fun close() {
		httpResponse.close()
	}

	internal fun completeIteration() {
		// close 'data' section in json
		iterationState = IterationState.AFTER_ITERATION
		jsonReader.endArray()

		// read other sections
		while (jsonReader.hasNext()) {
			val keyName = jsonReader.nextName()
			when (keyName) {
				"rows" -> {
					this.rows = jsonReader.nextLong()
				}

				"statistics" -> {
					this.statistic = readStatistics(jsonReader)
				}

				"rows_before_limit_at_least" -> {
					this.rowsBeforeLimitAtLeast = jsonReader.nextLong()
				}
			}
		}

		// complete response reading
		jsonReader.endObject()
	}


	// setters/getters
	override fun getMeta(): Meta {
		// Meta is always available, we can read it before response iteration
		// So no checks are needed
		return meta
	}

	override fun getStatistic(): Statistics {
		check(iterationState == IterationState.AFTER_ITERATION) {
			"Statistic isn't available yet, please read all data rows first"
		}

		return requireNotNull(statistic)
	}

	override fun getRows(): Long {
		check(iterationState == IterationState.AFTER_ITERATION) {
			"Rows isn't available yet, please read all data rows first"
		}

		return requireNotNull(rows)
	}

	override fun getRowsBeforeLimitAtLeast(): Long? {
		check(iterationState == IterationState.AFTER_ITERATION) {
			"RowsBeforeLimitAtLeast isn't available yet, please read all data rows first"
		}

		return rowsBeforeLimitAtLeast
	}

}

private enum class IterationState {
	BEFORE_ITERATION,
	READY_TO_ITERATION,
	AFTER_ITERATION
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy