如何为Oracle方言添加optimizer hint #475
-
| 
         Oracle的optimizer hint语法如下: SELECT /*+ LEADING(e2 e1) USE_NL(e1) INDEX(e1 emp_emp_id_pk) 
           USE_MERGE(j) FULL(j) */
    e1.first_name, e1.last_name, j.job_id, sum(e2.salary) total_sal
  FROM employees e1, employees e2, job_history j
  WHERE e1.employee_id = e2.manager_id
    AND e1.employee_id = j.employee_id
    AND e1.hire_date = j.start_date
  GROUP BY e1.first_name, e1.last_name, j.job_id
  ORDER BY total_sal;需要在 const val OPTIMIZER_HINTS_KEY = "optimizerHints"
class ExtendedOracleFormatter(database: Database, beautifySql: Boolean, indentSize: Int) :
    OracleFormatter(database, beautifySql, indentSize) {
    // ⚠️注意:ktorm版本更新时,一定要同步更新该方法
    override fun visitSelect(expr: SelectExpression): SelectExpression {
        val optimizerHints: List<String>? = (expr.extraProperties[OPTIMIZER_HINTS_KEY] as? List<*>)?.mapNotNull { it as? String }
        if (optimizerHints.isNullOrEmpty()) {
            return super.visitSelect(expr)
        }
        // 以下为super.visitSelect(expr)代码,在select关键字后插入了optimizer hint
        writeKeyword("select ")
        // 插入optimizer hint
        write("/*+ ${optimizerHints.joinToString(" ")} */ ")
        // 插入optimizer hint END
        if (expr.isDistinct) {
            writeKeyword("distinct ")
        }
        // 剩余的super.visitSelect(expr)代码,此处省略
        ...
    }
}
fun SelectExpression.withOptimizerHints(hints: List<String>): SelectExpression {
    return this.copy(
        extraProperties = extraProperties.toMutableMap().apply { put(OPTIMIZER_HINTS_KEY, hints) }
    )
}
fun Query.withOptimizerHints(vararg hints: String): Query = withOptimizerHints(hints.toList())
fun Query.withOptimizerHints(hints: List<String>): Query {
    return this.withExpression(
        when (val expression = this.expression) {
            is SelectExpression -> expression.withOptimizerHints(hints)
            is UnionExpression -> throw IllegalStateException("Optimizer hints are not supported in a union expression.")
        }
    )
}
fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.withOptimizerHints(vararg hints: String): EntitySequence<E, T> = withOptimizerHints(hints.toList())
fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.withOptimizerHints(hints: List<String>): EntitySequence<E, T> {
    return this.withExpression(expression.withOptimizerHints(hints))
}optimizer hint保存在 database.exampleEntities.withOptimizerHints("index(example_table EXAMPLE_IDX1)", "hint2", "hint3")
    .filter { it.employee_id eq employee_id }
    .toList()这样写虽然能实现功能,但是重写的  | 
  
Beta Was this translation helpful? Give feedback.
      
      
          Answered by
          
            vincentlauvlwj
          
      
      
        Jan 31, 2023 
      
    
    Replies: 1 comment 3 replies
-
| 
         可以考虑写成嵌套查询 const val OPTIMIZER_HINTS_KEY: String = "optimizerHints"
class ExtendedOracleFormatter(
    database: Database, beautifySql: Boolean, indentSize: Int
) : OracleFormatter(database, beautifySql, indentSize) {
    @Suppress("UNCHECKED_CAST")
    override fun visitSelect(expr: SelectExpression): SelectExpression {
        val hints = expr.extraProperties[OPTIMIZER_HINTS_KEY] as? List<String>
        if (hints.isNullOrEmpty()) {
            return super.visitSelect(expr)
        }
        
        writeKeyword("select * ")
        write("/*+ ${hints.joinToString(" ")} */ ")
        newLine(Indentation.SAME)
        writeKeyword("from ")
        visitQuerySource(expr)
        newLine(Indentation.SAME)
        return expr
    }
} | 
  
Beta Was this translation helpful? Give feedback.
                  
                    3 replies
                  
                
            
      Answer selected by
        tzhao11
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment
  
        
    
可以考虑写成嵌套查询