src/main/kotlin/de/uapcore/lightpit/dao/postgres/PGIssueDao.kt

Thu, 19 Nov 2020 13:58:54 +0100

author
mike@uapl01.localdomain
date
Thu, 19 Nov 2020 13:58:54 +0100
changeset 159
86b5d8a1662f
child 164
003b08bb3f25
permissions
-rw-r--r--

migrates DAO classes

mike@159 1 /*
mike@159 2 * Copyright 2020 Mike Becker. All rights reserved.
mike@159 3 *
mike@159 4 * Redistribution and use in source and binary forms, with or without
mike@159 5 * modification, are permitted provided that the following conditions are met:
mike@159 6 *
mike@159 7 * 1. Redistributions of source code must retain the above copyright
mike@159 8 * notice, this list of conditions and the following disclaimer.
mike@159 9 *
mike@159 10 * 2. Redistributions in binary form must reproduce the above copyright
mike@159 11 * notice, this list of conditions and the following disclaimer in the
mike@159 12 * documentation and/or other materials provided with the distribution.
mike@159 13 *
mike@159 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
mike@159 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
mike@159 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
mike@159 17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
mike@159 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
mike@159 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
mike@159 20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
mike@159 21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
mike@159 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
mike@159 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
mike@159 24 *
mike@159 25 */
mike@159 26
mike@159 27 package de.uapcore.lightpit.dao.postgres
mike@159 28
mike@159 29 import de.uapcore.lightpit.dao.AbstractIssueDao
mike@159 30 import de.uapcore.lightpit.dao.Functions
mike@159 31 import de.uapcore.lightpit.entities.*
mike@159 32 import java.sql.Connection
mike@159 33 import java.sql.PreparedStatement
mike@159 34 import java.sql.ResultSet
mike@159 35 import java.sql.Types
mike@159 36
mike@159 37 class PGIssueDao(connection: Connection) : AbstractIssueDao() {
mike@159 38
mike@159 39 private val query = "select issueid, i.project, p.name as projectname, p.node as projectnode, " +
mike@159 40 "component, c.name as componentname, c.node as componentnode, " +
mike@159 41 "status, category, subject, i.description, " +
mike@159 42 "userid, username, givenname, lastname, mail, " +
mike@159 43 "created, updated, eta " +
mike@159 44 "from lpit_issue i " +
mike@159 45 "join lpit_project p on i.project = projectid " +
mike@159 46 "left join lpit_component c on component = c.id " +
mike@159 47 "left join lpit_user on userid = assignee "
mike@159 48 private val list = connection.prepareStatement(query +
mike@159 49 "where i.project = ? and coalesce(component, -1) = coalesce(?, component, -1)")
mike@159 50 private val listForVersion = connection.prepareStatement(
mike@159 51 "with issue_version as ( " +
mike@159 52 "select issueid, versionid from lpit_issue_affected_version union " +
mike@159 53 "select issueid, versionid from lpit_issue_resolved_version) " +
mike@159 54 query +
mike@159 55 "left join issue_version using (issueid) " +
mike@159 56 "where i.project = ? " +
mike@159 57 "and coalesce(versionid,-1) = ? and coalesce(component, -1) = coalesce(?, component, -1)"
mike@159 58 )
mike@159 59 private val find = connection.prepareStatement(query + "where issueid = ? ")
mike@159 60 private val insert = connection.prepareStatement(
mike@159 61 "insert into lpit_issue (project, component, status, category, subject, description, assignee, eta) " +
mike@159 62 "values (?, ?, ?::issue_status, ?::issue_category, ?, ?, ?, ?) returning issueid"
mike@159 63 )
mike@159 64 private val update = connection.prepareStatement(
mike@159 65 "update lpit_issue set " +
mike@159 66 "updated = now(), component = ?, status = ?::issue_status, category = ?::issue_category, " +
mike@159 67 "subject = ?, description = ?, assignee = ?, eta = ? where issueid = ?"
mike@159 68 )
mike@159 69 private val affectedVersions = connection.prepareStatement(
mike@159 70 "select versionid, name, status, ordinal, node " +
mike@159 71 "from lpit_version join lpit_issue_affected_version using (versionid) " +
mike@159 72 "where issueid = ? " +
mike@159 73 "order by ordinal, name"
mike@159 74 )
mike@159 75 private val clearAffected = connection.prepareStatement("delete from lpit_issue_affected_version where issueid = ?")
mike@159 76 private val insertAffected = connection.prepareStatement("insert into lpit_issue_affected_version (issueid, versionid) values (?,?)")
mike@159 77
mike@159 78 private val resolvedVersions = connection.prepareStatement(
mike@159 79 "select versionid, name, status, ordinal, node " +
mike@159 80 "from lpit_version v join lpit_issue_resolved_version using (versionid) " +
mike@159 81 "where issueid = ? " +
mike@159 82 "order by ordinal, name"
mike@159 83 )
mike@159 84 private val clearResolved = connection.prepareStatement("delete from lpit_issue_resolved_version where issueid = ?")
mike@159 85 private val insertResolved = connection.prepareStatement("insert into lpit_issue_resolved_version (issueid, versionid) values (?,?)")
mike@159 86 private val insertComment = connection.prepareStatement(
mike@159 87 "insert into lpit_issue_comment (issueid, comment, userid) values (?, ? ,?)"
mike@159 88 )
mike@159 89 private val updateComment = connection.prepareStatement(
mike@159 90 "update lpit_issue_comment set comment = ?, updated = now(), updatecount = updatecount+1 where commentid = ?"
mike@159 91 )
mike@159 92 private val listComments = connection.prepareStatement(
mike@159 93 "select * from lpit_issue_comment left join lpit_user using (userid) where issueid = ? order by created"
mike@159 94 )
mike@159 95
mike@159 96 override fun mapResult(rs: ResultSet): Issue {
mike@159 97 val project = Project(rs.getInt("project"))
mike@159 98 project.name = rs.getString("projectname")
mike@159 99 project.node = rs.getString("projectnode")
mike@159 100 val issue = Issue(rs.getInt("issueid"))
mike@159 101 issue.project = project
mike@159 102 issue.component = rs.getInt("component").let { id ->
mike@159 103 if (rs.wasNull()) {
mike@159 104 null
mike@159 105 } else {
mike@159 106 val component = Component(id)
mike@159 107 component.name = rs.getString("componentname")
mike@159 108 component.node = rs.getString("componentnode")
mike@159 109 component
mike@159 110 }
mike@159 111 }
mike@159 112 issue.status = IssueStatus.valueOf(rs.getString("status"))
mike@159 113 issue.category = IssueCategory.valueOf(rs.getString("category"))
mike@159 114 issue.subject = rs.getString("subject")
mike@159 115 issue.description = rs.getString("description")
mike@159 116 issue.assignee = PGUserDao.mapResult(rs).takeUnless { rs.wasNull() }
mike@159 117 issue.created = rs.getTimestamp("created")
mike@159 118 issue.updated = rs.getTimestamp("updated")
mike@159 119 issue.eta = rs.getDate("eta")
mike@159 120 return issue
mike@159 121 }
mike@159 122
mike@159 123 private fun updateVersionLists(instance: Issue) {
mike@159 124 clearAffected.setInt(1, instance.id)
mike@159 125 clearResolved.setInt(1, instance.id)
mike@159 126 insertAffected.setInt(1, instance.id)
mike@159 127 insertResolved.setInt(1, instance.id)
mike@159 128 clearAffected.executeUpdate()
mike@159 129 clearResolved.executeUpdate()
mike@159 130 for (v: Version in instance.affectedVersions) {
mike@159 131 insertAffected.setInt(2, v.id)
mike@159 132 insertAffected.executeUpdate()
mike@159 133 }
mike@159 134 for (v: Version in instance.resolvedVersions) {
mike@159 135 insertResolved.setInt(2, v.id)
mike@159 136 insertResolved.executeUpdate()
mike@159 137 }
mike@159 138 }
mike@159 139
mike@159 140 private fun setData(stmt: PreparedStatement, column: Int, instance: Issue): Int {
mike@159 141 var col = column
mike@159 142 setForeignKeyOrNull(stmt, ++col, instance.component, Component::id)
mike@159 143 stmt.setString(++col, instance.status.name)
mike@159 144 stmt.setString(++col, instance.category.name)
mike@159 145 stmt.setString(++col, instance.subject)
mike@159 146 Functions.setStringOrNull(stmt, ++col, instance.description)
mike@159 147 setForeignKeyOrNull(stmt, ++col, instance.assignee, User::id)
mike@159 148 Functions.setDateOrNull(stmt, ++col, instance.eta)
mike@159 149 return col
mike@159 150 }
mike@159 151
mike@159 152 override fun save(instance: Issue, parent: Project) {
mike@159 153 instance.project = parent
mike@159 154 var column = 0
mike@159 155 insert.setInt(++column, parent.id)
mike@159 156 setData(insert, column, instance)
mike@159 157 // insert and retrieve the ID
mike@159 158 val rs = insert.executeQuery()
mike@159 159 rs.next()
mike@159 160 instance.id = rs.getInt(1)
mike@159 161 updateVersionLists(instance)
mike@159 162 }
mike@159 163
mike@159 164 override fun update(instance: Issue): Boolean {
mike@159 165 var column = setData(update, 0, instance)
mike@159 166 update.setInt(++column, instance.id)
mike@159 167 return if (update.executeUpdate() > 0) {
mike@159 168 updateVersionLists(instance)
mike@159 169 true
mike@159 170 } else {
mike@159 171 false
mike@159 172 }
mike@159 173 }
mike@159 174
mike@159 175 override fun list(parent: Project): List<Issue> {
mike@159 176 list.setInt(1, parent.id)
mike@159 177 list.setNull(2, Types.INTEGER)
mike@159 178 return super.list(list)
mike@159 179 }
mike@159 180
mike@159 181 override fun list(project: Project, component: Component?, version: Version?): List<Issue> {
mike@159 182 listForVersion.setInt(1, project.id)
mike@159 183 listForVersion.setInt(2, version?.id ?: -1)
mike@159 184 listForVersion.setInt(3, component?.id ?: -1)
mike@159 185 return super.list(listForVersion)
mike@159 186 }
mike@159 187
mike@159 188 override fun list(project: Project, version: Version?): List<Issue> {
mike@159 189 listForVersion.setInt(1, project.id)
mike@159 190 listForVersion.setInt(2, version?.id ?: -1)
mike@159 191 listForVersion.setNull(3, Types.INTEGER)
mike@159 192 return super.list(listForVersion)
mike@159 193 }
mike@159 194
mike@159 195 override fun list(project: Project, component: Component?): List<Issue> {
mike@159 196 list.setInt(1, project.id)
mike@159 197 list.setInt(2, component?.id ?: -1)
mike@159 198 return super.list(list)
mike@159 199 }
mike@159 200
mike@159 201 override fun find(id: Int): Issue? {
mike@159 202 find.setInt(1, id)
mike@159 203 return super.find(find)
mike@159 204 }
mike@159 205
mike@159 206 private fun listVersions(stmt: PreparedStatement, issue: Issue): List<Version> {
mike@159 207 stmt.setInt(1, issue.id)
mike@159 208 return sequence {
mike@159 209 stmt.executeQuery().use { result ->
mike@159 210 while (result.next()) yield(PGVersionDao.mapResult(result))
mike@159 211 }
mike@159 212 }.toList()
mike@159 213 }
mike@159 214
mike@159 215 override fun joinVersionInformation(issue: Issue) {
mike@159 216 issue.affectedVersions = listVersions(affectedVersions, issue)
mike@159 217 issue.resolvedVersions = listVersions(resolvedVersions, issue)
mike@159 218 }
mike@159 219
mike@159 220 override fun listComments(issue: Issue): List<IssueComment> {
mike@159 221 listComments.setInt(1, issue.id)
mike@159 222 return sequence {
mike@159 223 listComments.executeQuery().use { rs ->
mike@159 224 while (rs.next()) {
mike@159 225 val comment = IssueComment(rs.getInt("commentid"))
mike@159 226 comment.created = rs.getTimestamp("created")
mike@159 227 comment.updated = rs.getTimestamp("updated")
mike@159 228 comment.updateCount = rs.getInt("updatecount")
mike@159 229 comment.comment = rs.getString("comment")
mike@159 230 comment.author = PGUserDao.mapResult(rs).takeUnless { rs.wasNull() }
mike@159 231 yield(comment)
mike@159 232 }
mike@159 233 }
mike@159 234 }.toList()
mike@159 235 }
mike@159 236
mike@159 237 override fun saveComment(issue: Issue, comment: IssueComment) {
mike@159 238 if (comment.id >= 0) {
mike@159 239 updateComment.setString(1, comment.comment)
mike@159 240 updateComment.setInt(2, comment.id)
mike@159 241 updateComment.execute()
mike@159 242 } else {
mike@159 243 insertComment.setInt(1, issue.id)
mike@159 244 insertComment.setString(2, comment.comment)
mike@159 245 setForeignKeyOrNull(insertComment, 3, comment.author, User::id)
mike@159 246 insertComment.execute()
mike@159 247 }
mike@159 248 }
mike@159 249 }

mercurial