feat: EXPOSED-418 Support comments on table columns#2728
feat: EXPOSED-418 Support comments on table columns#2728obabichevjb wants to merge 2 commits intomainfrom
Conversation
| /** | ||
| * Returns SQL statements to add/update a comment on the specified column. | ||
| * Returns empty list if comments are not supported. | ||
| */ | ||
| fun commentOnColumn(column: Column<*>, comment: String?): List<String> = emptyList() |
There was a problem hiding this comment.
A suggestion:
All the other schema DDL methods in this class are named with an action/verb and a noun.
I think it would be clearer to change the name to something like:
addColumnComment()
setColumnComment()
modifyColumnComment()
| listOf("ALTER TABLE $tableName ALTER COLUMN $columnDef") | ||
| } else { | ||
| if (comment != null) { | ||
| exposedLogger.warn("H2 doesn't support comments on columns. The comment on column of table $tableName could not be added.") |
There was a problem hiding this comment.
Minor: Maybe we could more that "H2 supports comments on columns only in MySQL/MariaDB mode..."
| val tableName = tr.identity(column.table) | ||
| val columnName = tr.identity(column) |
There was a problem hiding this comment.
Based on how this is used in the string below, would it not be equivalent to just using tr.fullIdentity(column)?
| val tableName = tr.identity(column.table) | ||
| val columnName = tr.identity(column) |
There was a problem hiding this comment.
Same comment as previously, why not replace with single tr.fullIdentity(column)?
| it.dbDefaultValue = this.dbDefaultValue | ||
| it.isDatabaseGenerated = this.isDatabaseGenerated | ||
| it.extraDefinitions = this.extraDefinitions | ||
| it.columnComment = this.columnComment |
There was a problem hiding this comment.
Please add similar line to the 3 other places where we don't want to lose existing column settings by chaining:
- Alias.kt ->
private fun <T> Column<T>.clone() - Table.kt ->
fun <T : Any> Column<T>.entityId() - Table.kt ->
fun <T : Any> Column<T>.nullable()
| """.trimIndent() | ||
| } | ||
|
|
||
| jdbcConnection.prepareStatement(sql).use { stmt -> |
There was a problem hiding this comment.
Could this not all be replaced with existing metadata.connection.executeSQL()?
It's a private function, so it could be adjusted if placeholders are necessary.
|
|
||
| // Apply migration | ||
| SchemaUtils.statementsRequiredToActualizeScheme(testTableV2).forEach { exec(it) } | ||
| commit() |
There was a problem hiding this comment.
Minor, but it would be great if we didn't introduce more usage of this deprecated method in tests if we don't have to.
I would suggest creating a new test file in exposed-migration-r2dbc and just copying all these migration tests over.
| // Migration Tests | ||
|
|
There was a problem hiding this comment.
Same comment as previously about not introducing more usage of this deprecated method in tests if we don't have to.
I would suggest creating a new test file in exposed-migration-jdbc and just copying all these migration tests over.
| */ | ||
| fun <T> Column<T>.comment(text: String?): Column<T> = apply { | ||
| columnComment = text | ||
| } |
There was a problem hiding this comment.
Questions about nullable text argument:
- Is PostgreSQL the only db that accepts SQL NULL as a comment?
- Does chaining
.comment(null)actually remove the comment in other db? I didn't see example of this in tests, would it be possible to add a test? - Let's say a user had a previous db schema with comment on column. Now they want to remove comment. Is there an advantage to altering column property to have
.comment(null)or is it same result as just removing.comment()entirely (like already seen intestRemoveComment())?
| /** | ||
| * Escapes special characters in comments to prevent SQL injection. | ||
| * Single quotes are doubled per SQL standard. | ||
| */ | ||
| protected fun String.escapeComment(): String = this.replace("'", "''") | ||
|
|
||
| /** | ||
| * Checks if the current dialect uses inline comments (MySQL syntax). | ||
| * Returns true for MySQL and H2 in MySQL/MariaDB compatibility modes. | ||
| */ | ||
| fun isInlineCommentDialect(): Boolean { | ||
| val isH2MysqlMode = currentDialect is H2Dialect && ( | ||
| currentDialect.h2Mode == H2Dialect.H2CompatibilityMode.MySQL || | ||
| currentDialect.h2Mode == H2Dialect.H2CompatibilityMode.MariaDB | ||
| ) | ||
| return currentDialect is MysqlDialect || isH2MysqlMode | ||
| } |
There was a problem hiding this comment.
I'm not sure I see the value in adding these to the public API.
Maybe escapeComment() could have future general uses.
But isInlineCommentDialect() seems very unlikely and doesn't feel like it's in the right place. It's not actually used by any of the dialect classes directly and every use of it would require an odd cast first. Since DatabaseDialect is what is normally more accessible via currentDialect or db.dialect.
I think we should try to avoid noise in the public API and make these top-level internal functions instead.
Would also reduce the duplication of escapeComment() in descriptionDdl.
We can always open them up if requested later?
Description
Add support for database comments on table columns, allowing developers to document column purposes directly in the database schema using the
.comment()extension function..comment(text: String?)extension function for columns with proper API documentationCOMMENT ON COLUMN table.column IS 'text'statementsCOLUMN_NAME TYPE COMMENT 'text'syntaxColumnDiffALL_COL_COMMENTScatalogREMARKScolumn to all database metadata queries.withDefinition("COMMENT")APIType of Change
Please mark the relevant options with an "X":
Affected databases:
Related Issues
Support comments on tables