Sat, 23 Jan 2021 14:47:59 +0100
fixes issue query returning issues more than once
1 /*
2 * Copyright 2021 Mike Becker. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
26 package de.uapcore.lightpit.dao
28 import de.uapcore.lightpit.entities.*
29 import de.uapcore.lightpit.filter.*
30 import de.uapcore.lightpit.types.WebColor
31 import java.sql.Connection
32 import java.sql.PreparedStatement
33 import java.sql.ResultSet
35 class PostgresDataAccessObject(private val connection: Connection) : DataAccessObject {
37 //<editor-fold desc="User">
38 private fun selectUserInfo(
39 rs: ResultSet,
40 idColumn: String = "userid",
41 usernameColumn: String = "username",
42 givennameColumn: String = "givenname",
43 lastnameColumn: String = "lastname",
44 mailColumn: String = "mail"
45 ): User? {
46 val idval = rs.getInt(idColumn)
47 return if (rs.wasNull()) null else {
48 User(idval).apply {
49 username = rs.getString(usernameColumn)
50 givenname = rs.getString(givennameColumn)
51 lastname = rs.getString(lastnameColumn)
52 mail = rs.getString(mailColumn)
53 }
54 }
55 }
57 private fun selectUsers(stmt: PreparedStatement) = sequence {
58 stmt.executeQuery().use { rs ->
59 while (rs.next()) selectUserInfo(rs)?.let { yield(it) }
60 }
61 }
63 //language=SQL
64 private val userQuery = "select userid, username, lastname, givenname, mail from lpit_user"
66 private val stmtUsers by lazy {
67 connection.prepareStatement(
68 """${userQuery}
69 where userid > 0
70 order by username
71 """
72 )
73 }
74 private val stmtUserByID by lazy {
75 connection.prepareStatement(
76 """${userQuery}
77 where userid = ?
78 """
79 )
80 }
81 private val stmtUserByName by lazy {
82 connection.prepareStatement(
83 """${userQuery}
84 where lower(username) = lower(?)
85 """
86 )
87 }
88 private val stmtInsertUser by lazy {
89 connection.prepareStatement(
90 "insert into lpit_user (username, lastname, givenname, mail) values (?, ?, ?, ?)"
91 )
92 }
93 private val stmtUpdateUser by lazy {
94 connection.prepareStatement(
95 "update lpit_user set lastname = ?, givenname = ?, mail = ? where userid = ?"
96 )
97 }
99 override fun listUsers() = selectUsers(stmtUsers).toList()
100 override fun findUser(id: Int): User? {
101 stmtUserByID.setInt(1, id)
102 return selectUsers(stmtUserByID).firstOrNull()
103 }
105 override fun findUserByName(username: String): User? {
106 stmtUserByName.setString(1, username)
107 return selectUsers(stmtUserByName).firstOrNull()
108 }
110 override fun insertUser(user: User) {
111 with(user) {
112 stmtInsertUser.setStringSafe(1, username)
113 stmtInsertUser.setStringOrNull(2, lastname)
114 stmtInsertUser.setStringOrNull(3, givenname)
115 stmtInsertUser.setStringOrNull(4, mail)
116 }
117 stmtInsertUser.execute()
118 }
120 override fun updateUser(user: User) {
121 with(user) {
122 stmtUpdateUser.setStringOrNull(1, lastname)
123 stmtUpdateUser.setStringOrNull(2, givenname)
124 stmtUpdateUser.setStringOrNull(3, mail)
125 stmtUpdateUser.setInt(4, id)
126 }
127 stmtUpdateUser.execute()
128 }
129 //</editor-fold>
131 //<editor-fold desc="Version">
132 private fun selectVersions(stmt: PreparedStatement) = sequence {
133 stmt.executeQuery().use { rs ->
134 while (rs.next()) {
135 yield(Version(rs.getInt("versionid"), rs.getInt("project")).apply {
136 name = rs.getString("name")
137 node = rs.getString("node")
138 ordinal = rs.getInt("ordinal")
139 status = rs.getEnum("status")
140 })
141 }
142 }
143 }
145 private fun setVersionFields(stmt: PreparedStatement, obj: Version): Int {
146 with(obj) {
147 stmt.setStringSafe(1, name)
148 stmt.setStringSafe(2, node)
149 stmt.setInt(3, ordinal)
150 stmt.setEnum(4, status)
151 }
152 return 5
153 }
155 //language=SQL
156 private val versionQuery = "select versionid, project, name, node, ordinal, status from lpit_version"
158 private val stmtVersions by lazy {
159 connection.prepareStatement(
160 """${versionQuery}
161 where project = ?
162 order by ordinal desc, lower(name) desc
163 """
164 )
165 }
166 private val stmtVersionByID by lazy {
167 connection.prepareStatement(
168 """${versionQuery}
169 where versionid = ?
170 """
171 )
172 }
173 private val stmtVersionByNode by lazy {
174 connection.prepareStatement(
175 """${versionQuery}
176 where project = ? and node = ?
177 """
178 )
179 }
180 private val stmtInsertVersion by lazy {
181 connection.prepareStatement(
182 """
183 insert into lpit_version (name, node, ordinal, status, project)
184 values (?, ?, ?, ?::version_status, ?)
185 """
186 )
187 }
188 private val stmtUpdateVersion by lazy {
189 connection.prepareStatement(
190 """
191 update lpit_version set name = ?, node = ?, ordinal = ?, status = ?::version_status
192 where versionid = ?
193 """
194 )
195 }
197 override fun listVersions(project: Project): List<Version> {
198 stmtVersions.setInt(1, project.id)
199 return selectVersions(stmtVersions).toList()
200 }
202 override fun findVersion(id: Int): Version? {
203 stmtVersionByID.setInt(1, id)
204 return selectVersions(stmtVersionByID).firstOrNull()
205 }
207 override fun findVersionByNode(project: Project, node: String): Version? {
208 stmtVersionByNode.setInt(1, project.id)
209 stmtVersionByNode.setString(2, node)
210 return selectVersions(stmtVersionByNode).firstOrNull()
211 }
213 override fun insertVersion(version: Version) {
214 val col = setVersionFields(stmtInsertVersion, version)
215 stmtInsertVersion.setInt(col, version.projectid)
216 stmtInsertVersion.execute()
217 }
219 override fun updateVersion(version: Version) {
220 val col = setVersionFields(stmtUpdateVersion, version)
221 stmtUpdateVersion.setInt(col, version.id)
222 stmtUpdateVersion.execute()
223 }
224 //</editor-fold>
226 //<editor-fold desc="Component">
227 private fun selectComponents(stmt: PreparedStatement) = sequence {
228 stmt.executeQuery().use { rs ->
229 while (rs.next()) {
230 yield(Component(rs.getInt("id"), rs.getInt("project")).apply {
231 name = rs.getString("name")
232 node = rs.getString("node")
233 color = try {
234 WebColor(rs.getString("color"))
235 } catch (ex: IllegalArgumentException) {
236 WebColor("000000")
237 }
238 ordinal = rs.getInt("ordinal")
239 description = rs.getString("description")
240 lead = selectUserInfo(rs)
241 })
242 }
243 }
244 }
246 private fun setComponentFields(stmt: PreparedStatement, obj: Component): Int {
247 with(obj) {
248 stmt.setStringSafe(1, name)
249 stmt.setStringSafe(2, node)
250 stmt.setStringSafe(3, color.hex)
251 stmt.setInt(4, ordinal)
252 stmt.setStringOrNull(5, description)
253 stmt.setIntOrNull(6, obj.lead?.id)
254 }
255 return 7
256 }
258 //language=SQL
259 private val componentQuery =
260 """
261 select id, project, name, node, color, ordinal, description,
262 userid, username, givenname, lastname, mail
263 from lpit_component
264 left join lpit_user on lead = userid
265 """
267 private val stmtComponents by lazy {
268 connection.prepareStatement(
269 """${componentQuery}
270 where project = ?
271 order by ordinal, lower(name)
272 """
273 )
274 }
275 private val stmtComponentById by lazy {
276 connection.prepareStatement(
277 """${componentQuery}
278 where id = ?
279 """
280 )
281 }
282 private val stmtComponentByNode by lazy {
283 connection.prepareStatement(
284 """${componentQuery}
285 where project = ? and node = ?
286 """
287 )
288 }
289 private val stmtInsertComponent by lazy {
290 connection.prepareStatement(
291 """
292 insert into lpit_component (name, node, color, ordinal, description, lead, project)
293 values (?, ?, ?, ?, ?, ?, ?)
294 """
295 )
296 }
297 private val stmtUpdateComponent by lazy {
298 connection.prepareStatement(
299 "update lpit_component set name = ?, node = ?, color = ?, ordinal = ?, description = ?, lead = ? where id = ?"
300 )
301 }
303 override fun listComponents(project: Project): List<Component> {
304 stmtComponents.setInt(1, project.id)
305 return selectComponents(stmtComponents).toList()
306 }
308 override fun findComponent(id: Int): Component? {
309 stmtComponentById.setInt(1, id)
310 return selectComponents(stmtComponentById).firstOrNull()
311 }
313 override fun findComponentByNode(project: Project, node: String): Component? {
314 stmtComponentByNode.setInt(1, project.id)
315 stmtComponentByNode.setString(2, node)
316 return selectComponents(stmtComponentByNode).firstOrNull()
317 }
319 override fun insertComponent(component: Component) {
320 val col = setComponentFields(stmtInsertComponent, component)
321 stmtInsertComponent.setInt(col, component.projectid)
322 stmtInsertComponent.execute()
323 }
325 override fun updateComponent(component: Component) {
326 val col = setComponentFields(stmtUpdateComponent, component)
327 stmtUpdateComponent.setInt(col, component.id)
328 stmtUpdateComponent.execute()
329 }
331 //</editor-fold>
333 //<editor-fold desc="Project">
335 private fun selectProjects(stmt: PreparedStatement) = sequence {
336 stmt.executeQuery().use { rs ->
337 while (rs.next()) {
338 yield(Project(rs.getInt("projectid")).apply {
339 name = rs.getString("name")
340 node = rs.getString("node")
341 ordinal = rs.getInt("ordinal")
342 description = rs.getString("description")
343 repoUrl = rs.getString("repourl")
344 owner = selectUserInfo(rs)
345 })
346 }
347 }
348 }
350 private fun setProjectFields(stmt: PreparedStatement, obj: Project): Int {
351 with(obj) {
352 stmt.setStringSafe(1, name)
353 stmt.setStringSafe(2, node)
354 stmt.setInt(3, ordinal)
355 stmt.setStringOrNull(4, description)
356 stmt.setStringOrNull(5, repoUrl)
357 stmt.setIntOrNull(6, owner?.id)
358 }
359 return 7
360 }
362 //language=SQL
363 private val projectQuery =
364 """
365 select projectid, name, node, ordinal, description, repourl,
366 userid, username, lastname, givenname, mail
367 from lpit_project
368 left join lpit_user owner on lpit_project.owner = owner.userid
369 """
371 private val stmtProjects by lazy {
372 connection.prepareStatement(
373 """${projectQuery}
374 order by ordinal, lower(name)
375 """
376 )
377 }
378 private val stmtProjectByID by lazy {
379 connection.prepareStatement(
380 """${projectQuery}
381 where projectid = ?
382 """
383 )
384 }
385 private val stmtProjectByNode by lazy {
386 connection.prepareStatement(
387 """${projectQuery}
388 where node = ?
389 """
390 )
391 }
392 private val stmtInsertProject by lazy {
393 connection.prepareStatement(
394 "insert into lpit_project (name, node, ordinal, description, repourl, owner) values (?, ?, ?, ?, ?, ?)"
395 )
396 }
397 private val stmtUpdateProject by lazy {
398 connection.prepareStatement(
399 "update lpit_project set name = ?, node = ?, ordinal = ?, description = ?, repourl = ?, owner = ? where projectid = ?"
400 )
401 }
402 private val stmtIssueSummary by lazy {
403 connection.prepareStatement(
404 """
405 select phase, count(*) as total
406 from lpit_issue
407 join lpit_issue_phases using(status)
408 where project = ?
409 group by phase
410 """
411 )
412 }
414 override fun listProjects(): List<Project> {
415 return selectProjects(stmtProjects).toList()
416 }
418 override fun findProject(id: Int): Project? {
419 stmtProjectByID.setInt(1, id)
420 return selectProjects(stmtProjectByID).firstOrNull()
421 }
423 override fun findProjectByNode(node: String): Project? {
424 stmtProjectByNode.setString(1, node)
425 return selectProjects(stmtProjectByNode).firstOrNull()
426 }
428 override fun insertProject(project: Project) {
429 setProjectFields(stmtInsertProject, project)
430 stmtInsertProject.execute()
431 }
433 override fun updateProject(project: Project) {
434 val col = setProjectFields(stmtUpdateProject, project)
435 stmtUpdateProject.setInt(col, project.id)
436 stmtUpdateProject.execute()
437 }
439 override fun collectIssueSummary(project: Project): IssueSummary {
440 stmtIssueSummary.setInt(1, project.id)
441 return stmtIssueSummary.executeQuery().use { rs ->
442 val summary = IssueSummary()
443 while (rs.next()) {
444 val phase = rs.getInt("phase")
445 val total = rs.getInt("total")
446 when (phase) {
447 0 -> summary.open = total
448 1 -> summary.active = total
449 2 -> summary.done = total
450 }
451 }
452 summary
453 }
454 }
456 //</editor-fold>
458 //<editor-fold desc="Issue">
460 private fun selectIssues(stmt: PreparedStatement) = sequence {
461 stmt.executeQuery().use { rs ->
462 while (rs.next()) {
463 val proj = Project(rs.getInt("project")).apply {
464 name = rs.getString("projectname")
465 node = rs.getString("projectnode")
466 }
467 val comp = rs.getInt("component").let {
468 if (rs.wasNull()) null else
469 Component(it, proj.id).apply {
470 name = rs.getString("componentname")
471 node = rs.getString("componentnode")
472 }
473 }
474 val issue = Issue(rs.getInt("issueid"), proj, comp).apply {
475 component = comp
476 status = rs.getEnum("status")
477 category = rs.getEnum("category")
478 subject = rs.getString("subject")
479 description = rs.getString("description")
480 assignee = selectUserInfo(rs)
481 created = rs.getTimestamp("created")
482 updated = rs.getTimestamp("updated")
483 eta = rs.getDate("eta")
484 }
485 queryAffectedVersions.setInt(1, issue.id)
486 issue.affectedVersions = selectVersions(queryAffectedVersions).toList()
487 queryResolvedVersions.setInt(1, issue.id)
488 issue.resolvedVersions = selectVersions(queryResolvedVersions).toList()
489 yield(issue)
490 }
491 }
492 }
494 private fun setIssueFields(stmt: PreparedStatement, obj: Issue): Int {
495 with(obj) {
496 stmt.setIntOrNull(1, component?.id)
497 stmt.setEnum(2, status)
498 stmt.setEnum(3, category)
499 stmt.setStringSafe(4, subject)
500 stmt.setStringOrNull(5, description)
501 stmt.setIntOrNull(6, assignee?.id)
502 stmt.setDateOrNull(7, eta)
503 }
504 return 8
505 }
507 //language=SQL
508 private val issueQuery =
509 """
510 select issueid,
511 i.project, p.name as projectname, p.node as projectnode,
512 component, c.name as componentname, c.node as componentnode,
513 status, category, subject, i.description,
514 userid, username, givenname, lastname, mail,
515 created, updated, eta
516 from lpit_issue i
517 join lpit_project p on i.project = projectid
518 left join lpit_component c on component = c.id
519 left join lpit_user on userid = assignee
520 """
522 private val queryResolvedVersions by lazy {
523 connection.prepareStatement(
524 """
525 select versionid, project, name, status, ordinal, node
526 from lpit_version v join lpit_issue_resolved_version using (versionid)
527 where issueid = ?
528 order by ordinal, name
529 """
530 )
531 }
533 private val queryAffectedVersions by lazy {
534 connection.prepareStatement(
535 """
536 select versionid, project, name, status, ordinal, node
537 from lpit_version join lpit_issue_affected_version using (versionid)
538 where issueid = ?
539 order by ordinal, name
540 """
541 )
542 }
544 private val stmtIssues by lazy {
545 connection.prepareStatement(
546 """
547 with issue_version as (
548 select issueid, versionid from lpit_issue_affected_version
549 union select issueid, versionid from lpit_issue_resolved_version
550 ),
551 filteterd_issues as (
552 select distinct issueid from lpit_issue
553 left join issue_version using (issueid)
554 where
555 (not ? or project = ?) and
556 (not ? or versionid = ?) and (not ? or versionid is null) and
557 (not ? or component = ?) and (not ? or component is null)
558 )
559 ${issueQuery} join filteterd_issues using (issueid)
560 """
561 )
562 }
564 private val fproj = 1
565 private val projectid = 2
566 private val fversion = 3
567 private val versionid = 4
568 private val nversion = 5
569 private val fcomp = 6
570 private val component = 7
571 private val ncomp = 8
573 private fun <T : Entity> applyFilter(filter: Filter<T>, fflag: Int, nflag: Int, idcol: Int) {
574 when (filter) {
575 is AllFilter -> {
576 stmtIssues.setBoolean(fflag, false)
577 stmtIssues.setBoolean(nflag, false)
578 stmtIssues.setInt(idcol, 0)
579 }
580 is NoneFilter -> {
581 stmtIssues.setBoolean(fflag, false)
582 stmtIssues.setBoolean(nflag, true)
583 stmtIssues.setInt(idcol, 0)
584 }
585 is SpecificFilter -> {
586 stmtIssues.setBoolean(fflag, true)
587 stmtIssues.setBoolean(nflag, false)
588 stmtIssues.setInt(idcol, filter.obj.id)
589 }
590 else -> {
591 TODO("Implement range filter.")
592 }
593 }
594 }
596 override fun listIssues(filter: IssueFilter): List<Issue> {
597 when (filter.project) {
598 is AllFilter -> {
599 stmtIssues.setBoolean(fproj, false)
600 stmtIssues.setInt(projectid, 0)
601 }
602 is SpecificFilter -> {
603 stmtIssues.setBoolean(fproj, true)
604 stmtIssues.setInt(projectid, filter.project.obj.id)
605 }
606 else -> throw IllegalArgumentException()
607 }
608 applyFilter(filter.version, fversion, nversion, versionid)
609 applyFilter(filter.component, fcomp, ncomp, component)
611 return selectIssues(stmtIssues).toList()
612 }
614 private val stmtFindIssueByID by lazy {
615 connection.prepareStatement(
616 """${issueQuery}
617 where issueid = ?
618 """
619 )
620 }
621 private val stmtInsertIssue by lazy {
622 connection.prepareStatement(
623 """
624 insert into lpit_issue (component, status, category, subject, description, assignee, eta, project)
625 values (?, ?::issue_status, ?::issue_category, ?, ?, ?, ?, ?)
626 returning issueid
627 """
628 )
629 }
630 private val stmtUpdateIssue by lazy {
631 connection.prepareStatement(
632 """
633 update lpit_issue set updated = now(),
634 component = ?, status = ?::issue_status, category = ?::issue_category, subject = ?,
635 description = ?, assignee = ?, eta = ?
636 where issueid = ?
637 """
638 )
639 }
640 private val stmtInsertAffectedVersion by lazy {
641 connection.prepareStatement(
642 "insert into lpit_issue_affected_version (issueid, versionid) values (?,?)"
643 )
644 }
645 private val stmtInsertResolvedVersion by lazy {
646 connection.prepareStatement(
647 "insert into lpit_issue_resolved_version (issueid, versionid) values (?,?)"
648 )
649 }
650 private val stmtClearAffectedVersions by lazy {
651 connection.prepareStatement("delete from lpit_issue_affected_version where issueid = ?")
652 }
653 private val stmtClearResolvedVersions by lazy {
654 connection.prepareStatement("delete from lpit_issue_resolved_version where issueid = ?")
655 }
657 override fun findIssue(id: Int): Issue? {
658 stmtFindIssueByID.setInt(1, id)
659 return selectIssues(stmtFindIssueByID).firstOrNull()
660 }
662 private fun insertVersionInfo(issue: Issue) {
663 stmtInsertAffectedVersion.setInt(1, issue.id)
664 stmtInsertResolvedVersion.setInt(1, issue.id)
665 issue.affectedVersions.forEach {
666 stmtInsertAffectedVersion.setInt(2, it.id)
667 stmtInsertAffectedVersion.execute()
668 }
669 issue.resolvedVersions.forEach {
670 stmtInsertResolvedVersion.setInt(2, it.id)
671 stmtInsertResolvedVersion.execute()
672 }
673 }
675 override fun insertIssue(issue: Issue) {
676 val col = setIssueFields(stmtInsertIssue, issue)
677 stmtInsertIssue.setInt(col, issue.project.id)
678 stmtInsertIssue.executeQuery().use { rs ->
679 rs.next()
680 issue.id = rs.getInt(1)
681 }
682 insertVersionInfo(issue)
683 }
685 override fun updateIssue(issue: Issue) {
686 val col = setIssueFields(stmtUpdateIssue, issue)
687 stmtUpdateIssue.setInt(col, issue.id)
688 stmtUpdateIssue.execute()
689 // TODO: improve by only inserting / deleting changed version information
690 stmtClearAffectedVersions.setInt(1, issue.id)
691 stmtClearResolvedVersions.setInt(1, issue.id)
692 stmtClearAffectedVersions.execute()
693 stmtClearResolvedVersions.execute()
694 insertVersionInfo(issue)
695 }
697 //</editor-fold>
699 //<editor-fold desc="IssueComment">
701 private fun selectComments(stmt: PreparedStatement) = sequence {
702 stmt.executeQuery().use { rs ->
703 while (rs.next()) {
704 yield(IssueComment(rs.getInt("commentid"), rs.getInt("issueid")).apply {
705 created = rs.getTimestamp("created")
706 updated = rs.getTimestamp("updated")
707 updateCount = rs.getInt("updatecount")
708 comment = rs.getString("comment")
709 author = selectUserInfo(rs)
710 })
711 }
712 }
713 }
715 private val stmtComments by lazy {
716 connection.prepareStatement(
717 "select * from lpit_issue_comment left join lpit_user using (userid) where issueid = ? order by created"
718 )
719 }
720 private val stmtInsertComment by lazy {
721 connection.prepareStatement(
722 "insert into lpit_issue_comment (issueid, comment, userid) values (?, ? ,?)"
723 )
724 }
725 private val stmtUpdateIssueDate by lazy {
726 connection.prepareStatement(
727 "update lpit_issue set updated = now() where issueid = ?"
728 )
729 }
731 override fun listComments(issue: Issue): List<IssueComment> {
732 stmtComments.setInt(1, issue.id)
733 return selectComments(stmtComments).toList()
734 }
736 override fun insertComment(issueComment: IssueComment) {
737 with(issueComment) {
738 stmtUpdateIssueDate.setInt(1, issueid)
739 stmtInsertComment.setInt(1, issueid)
740 stmtInsertComment.setStringSafe(2, comment)
741 stmtInsertComment.setIntOrNull(3, author?.id)
742 }
743 stmtInsertComment.execute()
744 stmtUpdateIssueDate.execute()
745 }
746 //</editor-fold>
747 }