@@ -11,7 +11,6 @@ import org.evomaster.client.java.controller.api.dto.database.schema.DbInfoDto
1111import org.evomaster.client.java.controller.api.dto.database.schema.ForeignKeyDto
1212import org.evomaster.client.java.controller.api.dto.database.schema.TableDto
1313import org.evomaster.core.logging.LoggingUtil
14- import org.evomaster.core.utils.StringUtils
1514import org.evomaster.dbconstraint.ConstraintDatabaseType
1615import org.evomaster.dbconstraint.ast.SqlCondition
1716import net.sf.jsqlparser.JSQLParserException
@@ -31,6 +30,9 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
3130
3231 private var parser = JSqlConditionParser ()
3332
33+ private val smtTables: List <SmtTable > = schema.tables.map { SmtTable (it) }
34+ private val smtTableByOriginalName: Map <String , SmtTable > = smtTables.associateBy { it.originalName }
35+
3436 /* *
3537 * Main method to generate SMT-LIB representation from SQL query.
3638 *
@@ -57,18 +59,15 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
5759 * @param smt The SMT-LIB object to which table definitions are added.
5860 */
5961 private fun appendTableDefinitions (smt : SMTLib ) {
60- for (table in schema.tables) {
61- val smtTableName = convertToAscii(table.id.name)
62- val dataTypeName = " ${StringUtils .capitalization(smtTableName)} Row"
63-
62+ for (smtTable in smtTables) {
6463 // Declare datatype for the table
6564 smt.addNode(
66- DeclareDatatypeSMTNode (dataTypeName, getConstructors(table ))
65+ DeclareDatatypeSMTNode (smtTable. dataTypeName, getConstructors(smtTable ))
6766 )
6867
6968 // Declare constants for each row
7069 for (i in 1 .. numberOfRows) {
71- smt.addNode(DeclareConstSMTNode (" ${smtTableName.lowercase() }$i " , dataTypeName))
70+ smt.addNode(DeclareConstSMTNode (" ${smtTable.smtName }$i " , smtTable. dataTypeName))
7271 }
7372 }
7473 }
@@ -79,23 +78,22 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
7978 * @param smt The SMT-LIB object to which table constraints are added.
8079 */
8180 private fun appendTableConstraints (smt : SMTLib ) {
82- for (table in schema.tables ) {
83- appendUniqueConstraints(smt, table )
84- appendCheckConstraints(smt, table )
81+ for (smtTable in smtTables ) {
82+ appendUniqueConstraints(smt, smtTable )
83+ appendCheckConstraints(smt, smtTable )
8584 }
8685 }
8786
8887 /* *
8988 * Appends unique constraints for each table to the SMT-LIB.
9089 *
9190 * @param smt The SMT-LIB object to which unique constraints are added.
92- * @param table The table for which unique constraints are added.
91+ * @param smtTable The table for which unique constraints are added.
9392 */
94- private fun appendUniqueConstraints (smt : SMTLib , table : TableDto ) {
95- val smtTableName = convertToAscii(table.id.name).lowercase()
96- for (column in table.columns) {
93+ private fun appendUniqueConstraints (smt : SMTLib , smtTable : SmtTable ) {
94+ for (column in smtTable.dto.columns) {
9795 if (column.unique) {
98- val nodes = assertForDistinctField(convertToAscii (column.name), smtTableName )
96+ val nodes = assertForDistinctField(smtTable.smtColumnName (column.name), smtTable.smtName )
9997 smt.addNodes(nodes)
10098 }
10199 }
@@ -105,14 +103,14 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
105103 * Appends check constraints for each table to the SMT-LIB.
106104 *
107105 * @param smt The SMT-LIB object to which check constraints are added.
108- * @param table The table for which check constraints are added.
106+ * @param smtTable The table for which check constraints are added.
109107 */
110- private fun appendCheckConstraints (smt : SMTLib , table : TableDto ) {
111- for (check in table .tableCheckExpressions) {
108+ private fun appendCheckConstraints (smt : SMTLib , smtTable : SmtTable ) {
109+ for (check in smtTable.dto .tableCheckExpressions) {
112110 try {
113111 val condition: SqlCondition = parser.parse(check.sqlCheckExpression, toDBType(schema.databaseType))
114112 for (i in 1 .. numberOfRows) {
115- val constraint: SMTNode = parseCheckExpression(table , condition, i)
113+ val constraint: SMTNode = parseCheckExpression(smtTable , condition, i)
116114 smt.addNode(constraint)
117115 }
118116 } catch (e: SqlConditionParserException ) {
@@ -126,13 +124,13 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
126124 /* *
127125 * Parses a check expression and returns the corresponding SMT node.
128126 *
129- * @param table The table containing the check expression.
127+ * @param smtTable The table containing the check expression.
130128 * @param condition The SQL condition to be parsed.
131129 * @param index The index of the row.
132130 * @return The corresponding SMT node.
133131 */
134- private fun parseCheckExpression (table : TableDto , condition : SqlCondition , index : Int ): SMTNode {
135- val visitor = SMTConditionVisitor (convertToAscii(table.id.name).lowercase() , emptyMap(), schema.tables, index)
132+ private fun parseCheckExpression (smtTable : SmtTable , condition : SqlCondition , index : Int ): SMTNode {
133+ val visitor = SMTConditionVisitor (smtTable.smtName , emptyMap(), schema.tables, index)
136134 return condition.accept(visitor, null ) as SMTNode
137135 }
138136
@@ -160,29 +158,28 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
160158 * @param smt The SMT-LIB object to which key constraints are added.
161159 */
162160 private fun appendKeyConstraints (smt : SMTLib ) {
163- for (table in schema.tables ) {
164- appendPrimaryKeyConstraints(smt, table )
165- appendForeignKeyConstraints(smt, table )
161+ for (smtTable in smtTables ) {
162+ appendPrimaryKeyConstraints(smt, smtTable )
163+ appendForeignKeyConstraints(smt, smtTable )
166164 }
167165 }
168166
169167 private fun appendBooleanConstraints (smt : SMTLib ) {
170- for (table in schema.tables) {
171- val smtTableName = convertToAscii(table.id.name).lowercase()
172- for (column in table.columns) {
168+ for (smtTable in smtTables) {
169+ for (column in smtTable.dto.columns) {
173170 if (column.type.equals(" BOOLEAN" , ignoreCase = true )) {
174- val columnName = convertToAscii (column.name).uppercase()
171+ val columnName = smtTable.smtColumnName (column.name).uppercase()
175172 for (i in 1 .. numberOfRows) {
176173 smt.addNode(
177174 AssertSMTNode (
178175 OrAssertion (
179176 listOf (
180- EqualsAssertion (listOf (" ($columnName $smtTableName $i )" , " \" true\" " )),
181- EqualsAssertion (listOf (" ($columnName $smtTableName $i )" , " \" True\" " )),
182- EqualsAssertion (listOf (" ($columnName $smtTableName $i )" , " \" TRUE\" " )),
183- EqualsAssertion (listOf (" ($columnName $smtTableName $i )" , " \" false\" " )),
184- EqualsAssertion (listOf (" ($columnName $smtTableName $i )" , " \" False\" " )),
185- EqualsAssertion (listOf (" ($columnName $smtTableName $i )" , " \" FALSE\" " ))
177+ EqualsAssertion (listOf (" ($columnName ${smtTable.smtName} $i )" , " \" true\" " )),
178+ EqualsAssertion (listOf (" ($columnName ${smtTable.smtName} $i )" , " \" True\" " )),
179+ EqualsAssertion (listOf (" ($columnName ${smtTable.smtName} $i )" , " \" TRUE\" " )),
180+ EqualsAssertion (listOf (" ($columnName ${smtTable.smtName} $i )" , " \" false\" " )),
181+ EqualsAssertion (listOf (" ($columnName ${smtTable.smtName} $i )" , " \" False\" " )),
182+ EqualsAssertion (listOf (" ($columnName ${smtTable.smtName} $i )" , " \" FALSE\" " ))
186183 )
187184 )
188185 )
@@ -194,27 +191,26 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
194191 }
195192
196193 private fun appendTimestampConstraints (smt : SMTLib ) {
197- for (table in schema.tables) {
198- val smtTableName = convertToAscii(table.id.name).lowercase()
199- for (column in table.columns) {
194+ for (smtTable in smtTables) {
195+ for (column in smtTable.dto.columns) {
200196 if (column.type.equals(" TIMESTAMP" , ignoreCase = true )) {
201- val columnName = convertToAscii (column.name).uppercase()
197+ val columnName = smtTable.smtColumnName (column.name).uppercase()
202198 val lowerBound = 0 // Example for Unix epoch start
203199 val upperBound = 32503680000 // Example for year 3000 in seconds
204200
205201 for (i in 1 .. numberOfRows) {
206202 smt.addNode(
207203 AssertSMTNode (
208204 GreaterThanOrEqualsAssertion (
209- " ($columnName $smtTableName $i )" ,
205+ " ($columnName ${smtTable.smtName} $i )" ,
210206 lowerBound.toString()
211207 )
212208 )
213209 )
214210 smt.addNode(
215211 AssertSMTNode (
216212 LessThanOrEqualsAssertion (
217- " ($columnName $smtTableName $i )" ,
213+ " ($columnName ${smtTable.smtName} $i )" ,
218214 upperBound.toString()
219215 )
220216 )
@@ -230,14 +226,13 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
230226 * Appends primary key constraints for each table to the SMT-LIB.
231227 *
232228 * @param smt The SMT-LIB object to which primary key constraints are added.
233- * @param table The table for which primary key constraints are added.
229+ * @param smtTable The table for which primary key constraints are added.
234230 */
235- private fun appendPrimaryKeyConstraints (smt : SMTLib , table : TableDto ) {
236- val smtTableName = convertToAscii(table.id.name).lowercase()
237- val primaryKeys = table.columns.filter { it.primaryKey }
231+ private fun appendPrimaryKeyConstraints (smt : SMTLib , smtTable : SmtTable ) {
232+ val primaryKeys = smtTable.dto.columns.filter { it.primaryKey }
238233
239234 for (primaryKey in primaryKeys) {
240- val nodes = assertForDistinctField(convertToAscii (primaryKey.name), smtTableName )
235+ val nodes = assertForDistinctField(smtTable.smtColumnName (primaryKey.name), smtTable.smtName )
241236 smt.addNodes(nodes)
242237 }
243238 }
@@ -272,20 +267,19 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
272267 * Appends foreign key constraints for each table to the SMT-LIB.
273268 *
274269 * @param smt The SMT-LIB object to which foreign key constraints are added.
275- * @param table The table for which foreign key constraints are added.
270+ * @param smtTable The table for which foreign key constraints are added.
276271 */
277- private fun appendForeignKeyConstraints (smt : SMTLib , table : TableDto ) {
278- val sourceTableName = convertToAscii(table.id.name).lowercase()
279-
280- for (foreignKey in table.foreignKeys) {
281- val referencedTable = findReferencedTable(foreignKey)
282- val referencedTableName = convertToAscii(referencedTable.id.name).lowercase()
283- val referencedColumnSelector = convertToAscii(findReferencedPKSelector(table, referencedTable, foreignKey))
272+ private fun appendForeignKeyConstraints (smt : SMTLib , smtTable : SmtTable ) {
273+ for (foreignKey in smtTable.dto.foreignKeys) {
274+ val referencedSmtTable = findReferencedSmtTable(foreignKey)
275+ val referencedColumnSelector = referencedSmtTable.smtColumnName(
276+ findReferencedPKSelector(smtTable.dto, referencedSmtTable.dto, foreignKey)
277+ )
284278
285279 for (sourceColumn in foreignKey.sourceColumns) {
286280 val nodes = assertForEqualsAny(
287- convertToAscii (sourceColumn), sourceTableName ,
288- referencedColumnSelector, referencedTableName
281+ smtTable.smtColumnName (sourceColumn), smtTable.smtName ,
282+ referencedColumnSelector, referencedSmtTable.smtName
289283 )
290284 smt.addNodes(nodes)
291285 }
@@ -353,13 +347,13 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
353347 }
354348
355349 /* *
356- * Finds the referenced table based on the foreign key.
350+ * Finds the [SmtTable] for the table referenced by the given foreign key.
357351 *
358352 * @param foreignKey The foreign key constraint.
359- * @return The referenced table .
353+ * @return The referenced [SmtTable] .
360354 */
361- private fun findReferencedTable (foreignKey : ForeignKeyDto ): TableDto {
362- return schema.tables.firstOrNull { it.id.name.equals( foreignKey.targetTable, ignoreCase = true ) }
355+ private fun findReferencedSmtTable (foreignKey : ForeignKeyDto ): SmtTable {
356+ return smtTableByOriginalName[ foreignKey.targetTable.lowercase()]
363357 ? : throw RuntimeException (" Referenced table not found: ${foreignKey.targetTable} " )
364358 }
365359
@@ -435,7 +429,9 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
435429 * @return The corresponding SMT node.
436430 */
437431 private fun parseQueryCondition (tableAliases : Map <String , String >, defaultTableName : String , condition : SqlCondition , index : Int ): SMTNode {
438- val visitor = SMTConditionVisitor (convertToAscii(defaultTableName), tableAliases, schema.tables, index)
432+ val smtDefaultTableName = smtTableByOriginalName[defaultTableName.lowercase()]?.smtName
433+ ? : convertToAscii(defaultTableName)
434+ val visitor = SMTConditionVisitor (smtDefaultTableName, tableAliases, schema.tables, index)
439435 return condition.accept(visitor, null ) as SMTNode
440436 }
441437
@@ -518,12 +514,10 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
518514 }
519515
520516 // Only add GetValueSMTNode for the mentioned tables
521- for (table in schema.tables) {
522- val tableNameLower = table.id.name.lowercase()
523- val smtColumnName = convertToAscii(tableNameLower)
524- if (tablesMentioned.contains(tableNameLower)) {
517+ for (smtTable in smtTables) {
518+ if (tablesMentioned.contains(smtTable.originalName)) {
525519 for (i in 1 .. numberOfRows) {
526- smt.addNode(GetValueSMTNode (" $smtColumnName $i " ))
520+ smt.addNode(GetValueSMTNode (" ${smtTable.smtName} $i " ))
527521 }
528522 }
529523 }
@@ -532,14 +526,14 @@ class SmtLibGenerator(private val schema: DbInfoDto, private val numberOfRows: I
532526 /* *
533527 * Gets the constructors for a table's columns to be used in SMT-LIB.
534528 *
535- * @param table The table for which constructors are generated.
529+ * @param smtTable The table for which constructors are generated.
536530 * @return A list of SMT nodes for column constructors.
537531 */
538- private fun getConstructors (table : TableDto ): List <DeclareConstSMTNode > {
539- return table .columns.map { c ->
532+ private fun getConstructors (smtTable : SmtTable ): List <DeclareConstSMTNode > {
533+ return smtTable.dto .columns.map { c ->
540534 val smtType = TYPE_MAP [c.type.uppercase()]
541535 ? : throw RuntimeException (" Unsupported column type: ${c.type} " )
542- DeclareConstSMTNode (convertToAscii (c.name), smtType)
536+ DeclareConstSMTNode (smtTable.smtColumnName (c.name), smtType)
543537 }
544538 }
545539
0 commit comments