Skip to content

Commit 2ec495a

Browse files
committed
Fixed an Internal Server Error, Caused when attempting to filter by a column whose data type is not a string.
1 parent 9e1864a commit 2ec495a

File tree

1 file changed

+47
-8
lines changed

1 file changed

+47
-8
lines changed

spra-play-server/src/main/scala/net/wiringbits/spra/admin/repositories/daos/DatabaseTablesDAO.scala

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import java.sql.{Connection, Date, PreparedStatement, ResultSet}
1010
import java.time.LocalDate
1111
import java.util.UUID
1212
import scala.collection.mutable.ListBuffer
13-
import scala.util.Try
14-
13+
import scala.util.{Failure, Success, Try}
1514
object DatabaseTablesDAO {
1615

1716
def all(schema: String = "public")(implicit conn: Connection): List[DatabaseTable] = {
@@ -73,6 +72,37 @@ object DatabaseTablesDAO {
7372
""".as(foreignKeyParser.*)
7473
}
7574

75+
private def columnTypeIsDouble(columnType: String): Boolean = {
76+
// 'contains' is used because PostgreSQL types may include additional details like precision or scale
77+
// https://www.postgresql.org/docs/8.1/datatype.html
78+
List("float", "decimal").exists(columnType.contains)
79+
}
80+
81+
private def columnTypeIsInt(columnType: String): Boolean = {
82+
List("int", "serial").exists(columnType.contains)
83+
}
84+
85+
private def isUUID(value: String, columnType: String): Boolean = {
86+
Try(UUID.fromString(value)) match {
87+
case Success(_) => columnType == "uuid"
88+
case Failure(_) => false
89+
}
90+
}
91+
92+
private def isInt(value: String, columnType: String): Boolean = {
93+
value.toIntOption.isDefined && columnTypeIsInt(columnType)
94+
}
95+
96+
private def isDecimal(value: String, columnType: String): Boolean = {
97+
value.toDoubleOption.isDefined && columnTypeIsDouble(columnType)
98+
}
99+
100+
private def isNumberOrUUID(value: String, columnType: String): Boolean = {
101+
isInt(value, columnType) ||
102+
isDecimal(value, columnType) ||
103+
isUUID(value, columnType)
104+
}
105+
76106
def getTableData(
77107
settings: TableSettings,
78108
columns: List[TableColumn],
@@ -88,12 +118,16 @@ object DatabaseTablesDAO {
88118

89119
val conditionsSql = queryParameters.filters
90120
.map { case FilterParameter(filterField, filterValue) =>
121+
val columnType = columns.find(_.name == filterField) match {
122+
case Some(column) => column.`type`
123+
case None => throw Exception(s"Column with name '$filterField' not found.")
124+
}
91125
filterValue match {
92-
case dateRegex(_, _, _) =>
126+
case dateRegex(_, _, _) if columnType == "date" =>
93127
s"DATE($filterField) = ?"
94128

95129
case _ =>
96-
if (filterValue.toIntOption.isDefined || filterValue.toDoubleOption.isDefined)
130+
if (isNumberOrUUID(filterValue, columnType))
97131
s"$filterField = ?"
98132
else
99133
s"$filterField LIKE ?"
@@ -111,20 +145,25 @@ object DatabaseTablesDAO {
111145
val preparedStatement = conn.prepareStatement(sql)
112146

113147
queryParameters.filters.zipWithIndex
114-
.foreach { case (FilterParameter(_, filterValue), index) =>
148+
.foreach { case (FilterParameter(filterField, filterValue), index) =>
115149
// We have to increment index by 1 because SQL parameterIndex starts in 1
116150
val sqlIndex = index + 1
117-
151+
val columnType = columns.find(_.name == filterField) match {
152+
case Some(column) => column.`type`
153+
case None => throw Exception(s"Column with name '$filterField' not found.")
154+
}
118155
filterValue match {
119156
case dateRegex(year, month, day) =>
120157
val parsedDate = LocalDate.of(year.toInt, month.toInt, day.toInt)
121158
preparedStatement.setDate(sqlIndex, Date.valueOf(parsedDate))
122159

123160
case _ =>
124-
if (filterValue.toIntOption.isDefined)
161+
if (isInt(filterValue, columnType))
125162
preparedStatement.setInt(sqlIndex, filterValue.toInt)
126-
else if (filterValue.toDoubleOption.isDefined)
163+
else if (isDecimal(filterValue, columnType))
127164
preparedStatement.setDouble(sqlIndex, filterValue.toDouble)
165+
else if (isUUID(filterValue, columnType))
166+
preparedStatement.setObject(sqlIndex, UUID.fromString(filterValue))
128167
else
129168
preparedStatement.setString(sqlIndex, s"%$filterValue%")
130169
}

0 commit comments

Comments
 (0)