1 /* 2 * Copyright 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.room.parser.optimization 18 19 import androidx.room.parser.ParsedQuery 20 import androidx.room.parser.SqlParser 21 import androidx.room.processor.QueryRewriter 22 import androidx.room.solver.query.result.QueryResultAdapter 23 24 /** 25 * If the query response has unused columns, this rewrites the query to only fetch those columns. 26 * 27 * e.g. if it is a query like `SELECT * FROM User` where only `name` and `lastName` columns are 28 * accessed in the generated code, this re-writer will change it to `SELECT name, lastName FROM 29 * (SELECT * FROM User)`. Sqlite takes care of the rest where it flattens the query to avoid 30 * fetching unused columns in intermediate steps. 31 */ 32 object RemoveUnusedColumnQueryRewriter : QueryRewriter { rewritenull33 override fun rewrite(query: ParsedQuery, resultAdapter: QueryResultAdapter): ParsedQuery { 34 // cannot do anything w/o a result info 35 val resultInfo = query.resultInfo ?: return query 36 if (resultAdapter.mappings.isEmpty()) { 37 return query 38 } 39 val usedColumns = resultAdapter.mappings.flatMap { it.usedColumns } 40 val columnNames = resultInfo.columns.map { it.name } 41 val unusedColumns = columnNames - usedColumns 42 if (unusedColumns.isEmpty()) { 43 return query // nothing to optimize here 44 } 45 if (columnNames.size != columnNames.distinct().size) { 46 // if result has duplicate columns, ignore for now 47 return query 48 } 49 val usedColumnNames = columnNames - unusedColumns 50 val updated = 51 SqlParser.parse( 52 "SELECT ${usedColumnNames.joinToString(", ") { "`$it`" }} FROM (${query.original})" 53 ) 54 if (updated.errors.isNotEmpty()) { 55 // we somehow messed up, return original 56 return query 57 } 58 return updated 59 } 60 } 61