diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt index 9b132d68..70e37cd7 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlBlock.kt @@ -36,9 +36,9 @@ import org.domaframework.doma.intellij.formatter.block.group.SqlNewGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnDefinitionRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateColumnAssignmentSymbolBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateSetGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.with.SqlWithColumnGroupBlock @@ -257,8 +257,6 @@ open class SqlBlock( is SqlInlineSecondGroupBlock -> { parentSetProcessor.updateInlineSecondGroupBlockParentAndAddGroup( - lastGroupBlock, - lastIndentLevel, childBlock, ) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlCommaBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlCommaBlock.kt index c3ceec6c..8505fde8 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlCommaBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlCommaBlock.kt @@ -20,6 +20,7 @@ import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.common.util.TypeUtil import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.condition.SqlConditionalExpressionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertColumnGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertValueGroupBlock @@ -48,6 +49,20 @@ open class SqlCommaBlock( context.enableFormat, context.formatMode, ) { + companion object { + private val EXPECTED_TYPES = + listOf( + SqlInsertColumnGroupBlock::class, + SqlInsertValueGroupBlock::class, + SqlUpdateSetGroupBlock::class, + SqlUpdateColumnGroupBlock::class, + SqlUpdateValueGroupBlock::class, + SqlFunctionParamBlock::class, + SqlWithColumnGroupBlock::class, + SqlKeywordGroupBlock::class, + ) + } + override val indent = ElementIndent( IndentType.COMMA, @@ -125,17 +140,7 @@ open class SqlCommaBlock( } override fun isSaveSpace(lastGroup: SqlBlock?): Boolean { - val expectedTypes = - listOf( - SqlInsertColumnGroupBlock::class, - SqlInsertValueGroupBlock::class, - SqlUpdateSetGroupBlock::class, - SqlUpdateColumnGroupBlock::class, - SqlUpdateValueGroupBlock::class, - SqlFunctionParamBlock::class, - SqlWithColumnGroupBlock::class, - SqlKeywordGroupBlock::class, - ) - return TypeUtil.isExpectedClassType(expectedTypes, parentBlock) + if (parentBlock is SqlConditionalExpressionGroupBlock) return false + return TypeUtil.isExpectedClassType(EXPECTED_TYPES, parentBlock) } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlDataTypeBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlDataTypeBlock.kt index 31898b95..ef633f56 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlDataTypeBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlDataTypeBlock.kt @@ -40,14 +40,14 @@ open class SqlDataTypeBlock( 0, ) - override fun setParentGroupBlock(lastGroupBlock: SqlBlock?) { - super.setParentGroupBlock(lastGroupBlock) + override fun setParentGroupBlock(lastGroup: SqlBlock?) { + super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.NONE indent.indentLen = 1 indent.groupIndentLen = indent.indentLen - if (lastGroupBlock is SqlCreateTableColumnDefinitionRawGroupBlock) { - lastGroupBlock.columnDataTypeBlock = this + if (lastGroup is SqlCreateTableColumnDefinitionRawGroupBlock) { + lastGroup.columnDataTypeBlock = this } } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt index 0ace76ed..9c404412 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/SqlRightPatternBlock.kt @@ -52,20 +52,48 @@ open class SqlRightPatternBlock( ) { var preSpaceRight = false + companion object { + private val NOT_INSERT_SPACE_TYPES = + listOf( + SqlFunctionParamBlock::class, + SqlInsertColumnGroupBlock::class, + SqlWithQuerySubGroupBlock::class, + SqlConflictExpressionSubGroupBlock::class, + ) + + private val INDENT_EXPECTED_TYPES = + listOf( + SqlUpdateColumnGroupBlock::class, + SqlUpdateValueGroupBlock::class, + SqlCreateTableColumnDefinitionGroupBlock::class, + ) + + private val NEW_LINE_EXPECTED_TYPES = + listOf( + SqlUpdateColumnGroupBlock::class, + SqlUpdateValueGroupBlock::class, + SqlCreateTableColumnDefinitionGroupBlock::class, + SqlColumnDefinitionRawGroupBlock::class, + SqlUpdateSetGroupBlock::class, + SqlWithQuerySubGroupBlock::class, + ) + + private val NEW_LINE_EXCLUDE_TYPES = + listOf( + SqlDataTypeParamBlock::class, + SqlConditionalExpressionGroupBlock::class, + SqlConflictExpressionSubGroupBlock::class, + SqlFunctionParamBlock::class, + ) + } + /** * Configures whether to add a space to the right side when the group ends. */ private fun enableLastRight() { parentBlock?.let { parent -> // Check if parent is in the notInsertSpaceClassList - val notInsertSpaceClassList = - listOf( - SqlFunctionParamBlock::class, - SqlInsertColumnGroupBlock::class, - SqlWithQuerySubGroupBlock::class, - SqlConflictExpressionSubGroupBlock::class, - ) - if (isExpectedClassType(notInsertSpaceClassList, parent)) { + if (isExpectedClassType(NOT_INSERT_SPACE_TYPES, parent)) { preSpaceRight = false return } @@ -118,13 +146,7 @@ open class SqlRightPatternBlock( parentBlock?.let { parent -> if (parent is SqlWithQuerySubGroupBlock) return 0 - val exceptionalTypes = - listOf( - SqlUpdateColumnGroupBlock::class, - SqlUpdateValueGroupBlock::class, - SqlCreateTableColumnDefinitionGroupBlock::class, - ) - if (isExpectedClassType(exceptionalTypes, parent)) return parent.indent.indentLen + if (isExpectedClassType(INDENT_EXPECTED_TYPES, parent)) return parent.indent.indentLen return parent.indent.indentLen } ?: return 0 } @@ -135,29 +157,11 @@ open class SqlRightPatternBlock( if (preSpaceRight) return false parentBlock?.let { parent -> - val exceptionalTypes = - listOf( - SqlCreateTableColumnDefinitionGroupBlock::class, - SqlColumnDefinitionRawGroupBlock::class, - SqlUpdateSetGroupBlock::class, - SqlUpdateColumnGroupBlock::class, - SqlUpdateValueGroupBlock::class, - SqlWithQuerySubGroupBlock::class, - ) - - val excludeTypes = - listOf( - SqlDataTypeParamBlock::class, - SqlConditionalExpressionGroupBlock::class, - SqlConflictExpressionSubGroupBlock::class, - SqlFunctionParamBlock::class, - ) - if (( - isExpectedClassType(exceptionalTypes, parent) || - isExpectedClassType(exceptionalTypes, parent.parentBlock) + isExpectedClassType(NEW_LINE_EXPECTED_TYPES, parent) || + isExpectedClassType(NEW_LINE_EXPECTED_TYPES, parent.parentBlock) ) && - !isExpectedClassType(excludeTypes, parent) + !isExpectedClassType(NEW_LINE_EXCLUDE_TYPES, parent) ) { return true } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlRawGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlRawGroupBlock.kt index 82de996c..fb74abf0 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlRawGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/column/SqlRawGroupBlock.kt @@ -15,8 +15,6 @@ */ package org.domaframework.doma.intellij.formatter.block.group.column -import com.intellij.formatting.Block -import com.intellij.formatting.Spacing import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock import org.domaframework.doma.intellij.formatter.block.SqlBlock @@ -44,11 +42,6 @@ abstract class SqlRawGroupBlock( 0, ) - override fun getSpacing( - p0: Block?, - p1: Block, - ): Spacing? = null - override fun buildChildren(): MutableList = mutableListOf() override fun isLeaf(): Boolean = true diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlInlineGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt similarity index 82% rename from src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlInlineGroupBlock.kt rename to src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt index e3fd73ff..fc6af15c 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlInlineGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineGroupBlock.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.formatter.block.group.keyword +package org.domaframework.doma.intellij.formatter.block.group.keyword.inline import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock @@ -29,6 +29,8 @@ open class SqlInlineGroupBlock( node, context, ) { + val inlineConditions: MutableList = mutableListOf() + override val indent = ElementIndent( IndentType.INLINE, @@ -40,15 +42,12 @@ open class SqlInlineGroupBlock( super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.INLINE indent.indentLen = createBlockIndentLen() - indent.groupIndentLen = indent.indentLen.plus(getNodeText().length) + indent.groupIndentLen = createGroupIndentLen() } override fun buildChildren(): MutableList = mutableListOf() - override fun createBlockIndentLen(): Int = - parentBlock?.let { - it.indent.groupIndentLen - .plus(it.getNodeText().length) - .plus(1) - } ?: 1 + override fun createBlockIndentLen(): Int = parentBlock?.indent?.groupIndentLen?.plus(1) ?: 1 + + override fun createGroupIndentLen(): Int = indent.indentLen.plus(getNodeText().length) } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlInlineSecondGroupBlock.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt similarity index 70% rename from src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlInlineSecondGroupBlock.kt rename to src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt index bdc1ae6f..5fe3eb3e 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/SqlInlineSecondGroupBlock.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/block/group/keyword/inline/SqlInlineSecondGroupBlock.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.domaframework.doma.intellij.formatter.block.group.keyword +package org.domaframework.doma.intellij.formatter.block.group.keyword.inline import com.intellij.lang.ASTNode import com.intellij.psi.formatter.common.AbstractBlock @@ -29,7 +29,7 @@ open class SqlInlineSecondGroupBlock( node, context, ) { - val isEndCase = getNodeText().lowercase() == "end" + val isEndCase = getNodeText() == "end" override val indent = ElementIndent( @@ -42,19 +42,28 @@ open class SqlInlineSecondGroupBlock( super.setParentGroupBlock(lastGroup) indent.indentLevel = IndentType.INLINE_SECOND indent.indentLen = createBlockIndentLen() - indent.groupIndentLen = indent.indentLen + indent.groupIndentLen = createGroupIndentLen() + } + + override fun setParentPropertyBlock(lastGroup: SqlBlock?) { + (lastGroup as? SqlInlineGroupBlock)?.inlineConditions?.add(this) } override fun buildChildren(): MutableList = mutableListOf() override fun createBlockIndentLen(): Int = - parentBlock?.let { + parentBlock?.let { parent -> // TODO:Customize indentation within an inline group if (isEndCase) { - it.indent.indentLen + val diffTextLength = parent.getNodeText().length.minus(getNodeText().length) + parent.indent.indentLen.plus(diffTextLength) } else { - it.indent.groupIndentLen - .plus(it.getNodeText().length) + parent.indent.groupIndentLen.plus(1) } } ?: 1 + + override fun createGroupIndentLen(): Int = indent.indentLen.plus(getNodeText().length) + + override fun isSaveSpace(lastGroup: SqlBlock?): Boolean = + (parentBlock as? SqlInlineGroupBlock)?.inlineConditions?.dropLast(1)?.isEmpty() != true } diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/processor/SqlSetParentGroupProcessor.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/processor/SqlSetParentGroupProcessor.kt index 0d5b6bb3..9de1aa61 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/processor/SqlSetParentGroupProcessor.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/processor/SqlSetParentGroupProcessor.kt @@ -24,11 +24,11 @@ import org.domaframework.doma.intellij.formatter.block.conflict.SqlDoGroupBlock import org.domaframework.doma.intellij.formatter.block.expr.SqlElConditionLoopCommentBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnDefinitionRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlLateralGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateViewGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlReturningGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.top.SqlTopQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.update.SqlUpdateQueryGroupBlock @@ -251,11 +251,7 @@ class SqlSetParentGroupProcessor( } } - fun updateInlineSecondGroupBlockParentAndAddGroup( - lastGroupBlock: SqlBlock, - lastIndentLevel: IndentType, - childBlock: SqlInlineSecondGroupBlock, - ) { + fun updateInlineSecondGroupBlockParentAndAddGroup(childBlock: SqlInlineSecondGroupBlock) { val context = SetParentContext( childBlock, @@ -276,13 +272,12 @@ class SqlSetParentGroupProcessor( } return } - if (lastIndentLevel == IndentType.INLINE_SECOND) { - blockBuilder.removeLastGroupTopNodeIndexHistory() - updateGroupBlockLastGroupParentAddGroup( - lastGroupBlock, - childBlock, - ) - return + val inlineSecondIndex = + blockBuilder.getGroupTopNodeIndex { block -> + block.indent.indentLevel == IndentType.INLINE_SECOND + } + if (inlineSecondIndex >= 0) { + blockBuilder.clearSubListGroupTopNodeIndexHistory(inlineSecondIndex) } updateGroupBlockParentAndAddGroup( childBlock, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockUtil.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockUtil.kt index 13041396..9ef80fa1 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockUtil.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlBlockUtil.kt @@ -36,8 +36,6 @@ import org.domaframework.doma.intellij.formatter.block.expr.SqlElConditionLoopCo import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnDefinitionRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.column.SqlColumnRawGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineGroupBlock -import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlJoinGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlKeywordGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.SqlLateralGroupBlock @@ -47,6 +45,8 @@ import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlC import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateTableColumnDefinitionGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateTableColumnDefinitionRawGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.create.SqlCreateViewGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineGroupBlock +import org.domaframework.doma.intellij.formatter.block.group.keyword.inline.SqlInlineSecondGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.insert.SqlInsertQueryGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlFromGroupBlock import org.domaframework.doma.intellij.formatter.block.group.keyword.second.SqlSecondKeywordBlock @@ -244,8 +244,11 @@ class SqlBlockUtil( ) } else { WithClauseUtil - .getWithClauseKeywordGroup(lastGroupBlock, child, sqlBlockFormattingCtx) - ?.let { return it } + .getWithClauseKeywordGroup( + lastGroupBlock, + child, + sqlBlockFormattingCtx, + )?.let { return it } return SqlSecondKeywordBlock( child, sqlBlockFormattingCtx, diff --git a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordUtil.kt b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordUtil.kt index 0feea2ec..df5d9239 100644 --- a/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordUtil.kt +++ b/src/main/kotlin/org/domaframework/doma/intellij/formatter/util/SqlKeywordUtil.kt @@ -24,18 +24,18 @@ enum class IndentType( TOP(1, true), SECOND(2, true), JOIN(3, true), + INLINE(2), + INLINE_SECOND(3, true), SECOND_OPTION(4, true), TIRD(5), ATTACHED(6), - INLINE_SECOND(8, true), - COLUMN(9, true), + COLUMN(7, true), SUB(90), ATTRIBUTE(91), LITERAL(92), COMMA(93), OPTIONS(94), PARAM(95), - INLINE(96), NONE(99), ; diff --git a/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt b/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt index b689a883..5720d9aa 100644 --- a/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt +++ b/src/test/kotlin/org/domaframework/doma/intellij/formatter/SqlFormatterTest.kt @@ -54,6 +54,10 @@ class SqlFormatterTest : BasePlatformTestCase() { formatSqlFile("Select.sql", "Select$formatDataPrefix.sql") } + fun testSelectCaseEndFormatter() { + formatSqlFile("SelectCaseEnd.sql", "SelectCaseEnd$formatDataPrefix.sql") + } + fun testSelectFromLateralFormatter() { formatSqlFile("SelectFromLateral.sql", "SelectFromLateral$formatDataPrefix.sql") } diff --git a/src/test/testData/sql/formatter/SelectCaseEnd.sql b/src/test/testData/sql/formatter/SelectCaseEnd.sql new file mode 100644 index 00000000..eb186684 --- /dev/null +++ b/src/test/testData/sql/formatter/SelectCaseEnd.sql @@ -0,0 +1,4 @@ +Select case when div = 'A' then 'AAA' +when div = 'B' then 'BBB' +else 'CCC' end as divName +from users \ No newline at end of file diff --git a/src/test/testData/sql/formatter/SelectCaseEnd_format.sql b/src/test/testData/sql/formatter/SelectCaseEnd_format.sql new file mode 100644 index 00000000..d738f099 --- /dev/null +++ b/src/test/testData/sql/formatter/SelectCaseEnd_format.sql @@ -0,0 +1,5 @@ +SELECT CASE WHEN div = 'A' THEN 'AAA' + WHEN div = 'B' THEN 'BBB' + ELSE 'CCC' + END AS divName + FROM users