dave08
10/10/2024, 1:27 PMdave08
10/10/2024, 1:27 PMinternal class JasyncQueryVisitor(
val conn: SuspendingConnection,
val config: DatabaseConfig = DryRunDatabaseConfig
) : QueryVisitor<JasyncRunner<*>> {
override fun <T, R> templateSelectQuery(
context: TemplateSelectContext,
transform: (Row) -> T,
collect: suspend (Flow<T>) -> R
): JasyncRunner<*> = JasyncRunner {
val runner = TemplateSelectRunner(context)
val stmt = runner.dryRun(config)
val result = try {
if (stmt.args.isEmpty())
conn.sendQuery(stmt.sql)
else
conn.sendPreparedStatement(
stmt.sql,
stmt.args.map { it.any }
)
} catch (e: Exception) {
println("Error running: ${context.sql} with params: ${context.valueMap}")
throw e
}
val flow = result.rows.asFlow()
.map { transform(RowDataWrapper(it)) }
collect(flow)
}
override fun <T : Any, R> templateEntityProjectionSelectQuery(
context: TemplateSelectContext,
metamodel: EntityMetamodel<T, *, *>,
strategy: ProjectionType,
collect: suspend (Flow<T>) -> R
): JasyncRunner<*> {
TODO("Not yet implemented")
}
override fun templateExecuteQuery(context: TemplateExecuteContext): JasyncRunner<Long> =
JasyncRunner { conn.sendQuery(context.sql).rowsAffected }
dave08
10/10/2024, 1:27 PMtemplateEntityProjectionSelectQuery
needs to be implemented here...dave08
10/10/2024, 1:27 PM@JvmInline
internal value class RowDataWrapper(private val rowData: RowData) : Row {
@Suppress("UNCHECKED_CAST")
override fun <T : Any> get(columnLabel: String, type: KType): T? {
return rowData[columnLabel] as? T
}
@Suppress("UNCHECKED_CAST")
override fun <T : Any> get(index: Int, type: KType): T? {
return rowData[index] as? T
}
}
dave08
10/10/2024, 1:50 PMoverride fun <T : Any, R> templateEntityProjectionSelectQuery(
context: TemplateSelectContext,
metamodel: EntityMetamodel<T, *, *>,
strategy: ProjectionType,
collect: suspend (Flow<T>) -> R
): JasyncRunner<*> = JasyncRunner {
val result = queryResult(context)
val transform: (RowData) -> T = when (strategy) {
ProjectionType.INDEX -> { row ->
val props = metamodel.properties().take(row.size).mapIndexed { index, propertyMetamodel ->
propertyMetamodel to row[index]
}
metamodel.newEntity(props.toMap())
}
ProjectionType.NAME -> { row ->
val props = metamodel.properties().mapNotNull { propertyMetamodel ->
propertyMetamodel to row[propertyMetamodel.columnName]
}
metamodel.newEntity(props.toMap())
}
}
val flow = result.rows.asFlow().map { transform(it) }
collect(flow)
}
dave08
10/10/2024, 1:58 PMdave08
10/10/2024, 1:59 PMdave08
10/10/2024, 4:02 PMinternal class JasyncQueryVisitor(
val conn: SuspendingConnection,
val config: DatabaseConfig = DryRunDatabaseConfig
) : QueryVisitor<JasyncRunner<*>> {
override fun <T, R> templateSelectQuery(
context: TemplateSelectContext,
transform: (Row) -> T,
collect: suspend (Flow<T>) -> R
): JasyncRunner<*> = JasyncRunner {
val result = queryResult(context)
val flow = result.rows.asFlow()
.map { transform(RowDataWrapper(it)) }
collect(flow)
}
private suspend fun queryResult(context: TemplateSelectContext): QueryResult {
val runner = TemplateSelectRunner(context)
val stmt = runner.dryRun(config)
val result = try {
if (stmt.args.isEmpty())
conn.sendQuery(stmt.sql)
else
conn.sendPreparedStatement(
stmt.sql,
stmt.args.map { it.any }
)
} catch (e: Exception) {
println("Error running: ${context.sql} with params: ${context.valueMap}")
throw e
}
return result
}
override fun <T : Any, R> templateEntityProjectionSelectQuery(
context: TemplateSelectContext,
metamodel: EntityMetamodel<T, *, *>,
strategy: ProjectionType,
collect: suspend (Flow<T>) -> R
): JasyncRunner<*> = JasyncRunner {
val result = queryResult(context)
val transform: (RowData) -> T = when (strategy) {
ProjectionType.INDEX -> { row ->
val props = metamodel.properties().take(row.size).mapIndexed { index, propertyMetamodel ->
propertyMetamodel to execute(propertyMetamodel, row, index)
}
metamodel.newEntity(props.toMap())
}
ProjectionType.NAME -> { row ->
val props = metamodel.properties().mapNotNull { propertyMetamodel ->
propertyMetamodel to execute(propertyMetamodel, row)
}
metamodel.newEntity(props.toMap())
}
}
val flow = result.rows.asFlow().map { transform(it) }
collect(flow)
}
fun <EXTERIOR : Any, INTERIOR : Any> execute(expression: ColumnExpression<EXTERIOR, INTERIOR>, row: RowData, index: Int): EXTERIOR? {
return ValueExtractor.getByIndex(expression, index) {
row[index] as INTERIOR?
}
}
fun <EXTERIOR : Any, INTERIOR : Any> execute(expression: ColumnExpression<EXTERIOR, INTERIOR>, row: RowData): EXTERIOR? {
return ValueExtractor.getByName(expression) {
row[expression.columnName] as INTERIOR?
}
}
Toshihiro Nakamura
10/10/2024, 11:14 PM