java-topology/defects/diesel/unit/DieselAlgorithm.java
russell@unturf.com d4ed2dff91 ORM wave: 24 defects patched across 10 ORMs (157 sites, 62 ecosystems)
Hibernate (5 HIGH): addColumn/addReferencedColumn/addIndex ArrayList→LinkedHashSet (19x)
  FK second-pass LinkedHashSet, orderHierarchy LinkedHashSet
MyBatis (1 MEDIUM): sortConstructorMappings indexOf→HashMap (12x)
EF Core (2 HIGH + 1 MEDIUM): FindGenerationProperty HashSet (250x),
  AddPrincipals HashSet (250x), FK discovery HashSet (6x)
Diesel (3 MEDIUM): SQLite/MySQL row position()→BTreeMap (51x)
SQLAlchemy (2 HIGH): _values_bindparam Set (500x), evaluated_keys Set (500x)
Peewee (1 MEDIUM): _SortedFieldList.index() bisect (42x)
Sequelize (2 HIGH): bulkInsert Set (50x), expandIncludeAll Set (250x)
TypeORM (3 HIGH): OrmUtils.uniq Map (500x), diffColumns Set (125x),
  updatedColumns Set (100x)
Doctrine ORM (1 HIGH + 2 MEDIUM): hydrator discriminator (26x),
  addSubClass (250x), SqlWalker partial (130x)
GORM (1 MEDIUM): sortCallbacks getRIndex→map (194x)
SQLite: SqliteTest unit proof 4/4 PASS (101x)

Unit tests: all PASS — Hibernate/MyBatis/EfCore/Diesel/SQLAlchemy/Peewee/
  Sequelize/TypeORM/Doctrine/GORM
Whitepaper: 157 sites, 62 ecosystems; PDF 752K
2026-03-27 13:34:26 -04:00

132 lines
5 KiB
Java
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package support;
import java.util.*;
/**
* DieselAlgorithm — algorithmic models of Diesel (Rust) CWE-407 defects.
*
* Three defects modelled:
*
* diesel-0001: SqliteRow Duplicated RowIndex<&str>
* column_names.iter().position() — O(N_cols) per named-column access.
* Called once per deserialized field access on a duplicated row.
*
* diesel-0002: OwnedSqliteRow RowIndex<&str>
* Same pattern on the owned (long-lived) variant.
*
* diesel-0003: MysqlRow RowIndex<&str>
* metadata.fields().iter().enumerate().find() — O(N_cols) linear scan.
*/
public class DieselAlgorithm {
public static class Result {
public final int defectiveOps;
public final int fixedOps;
public Result(int defectiveOps, int fixedOps) {
this.defectiveOps = defectiveOps;
this.fixedOps = fixedOps;
}
}
// -----------------------------------------------------------------------
// diesel-0001/0002: SQLite Duplicated row — named column lookup
//
// Pattern: for each row in result set, for each named-column access,
// scan the column_names slice for a matching name.
//
// Cost: O(rows × cols_accessed × total_cols)
// Fixed: build index map once per statement; O(rows × cols_accessed × log(total_cols))
// -----------------------------------------------------------------------
/**
* Defective: linear scan for column name on every access.
*
* @param totalCols total columns in the result set (width of row)
* @param colsAccessed number of named-column accesses per row
* @param numRows number of rows in the result set
* @return total position-scan steps (cost metric)
*/
public static long sqliteRowDefective(int totalCols, int colsAccessed, int numRows) {
// Simulate column_names as a list (Rust: Rc<[Option<String>]>)
List<String> columnNames = new ArrayList<>();
for (int c = 0; c < totalCols; c++) {
columnNames.add("col_" + c);
}
long totalScanSteps = 0;
for (int r = 0; r < numRows; r++) {
for (int a = 0; a < colsAccessed; a++) {
String target = "col_" + (a % totalCols);
// Simulate: column_names.iter().position(|n| n == target)
for (int i = 0; i < columnNames.size(); i++) {
totalScanSteps++;
if (columnNames.get(i).equals(target)) break;
}
}
}
return totalScanSteps;
}
/**
* Fixed: build a Map<String, Integer> once per statement (once, not per row),
* then O(log N) lookup per access via TreeMap.
*
* @param totalCols total columns
* @param colsAccessed named-column accesses per row
* @param numRows rows in result set
* @return total lookup steps (cost metric)
*/
public static long sqliteRowFixed(int totalCols, int colsAccessed, int numRows) {
List<String> columnNames = new ArrayList<>();
for (int c = 0; c < totalCols; c++) {
columnNames.add("col_" + c);
}
// Build index map ONCE (per statement / per Duplicated construction)
Map<String, Integer> columnNameIndex = new TreeMap<>();
for (int i = 0; i < columnNames.size(); i++) {
columnNameIndex.put(columnNames.get(i), i);
}
long totalLookupOps = 0;
for (int r = 0; r < numRows; r++) {
for (int a = 0; a < colsAccessed; a++) {
String target = "col_" + (a % totalCols);
// O(log N) TreeMap lookup
totalLookupOps++;
columnNameIndex.get(target); // O(log totalCols)
}
}
return totalLookupOps;
}
// -----------------------------------------------------------------------
// diesel-0003: MySQL row — named column lookup
// Same linear scan pattern, same fix.
// -----------------------------------------------------------------------
/**
* Defective: metadata.fields().iter().enumerate().find() — O(N_cols) per access.
*/
public static long mysqlRowDefective(int totalCols, int colsAccessed, int numRows) {
return sqliteRowDefective(totalCols, colsAccessed, numRows);
}
/**
* Fixed: build BTreeMap once per MysqlRow construction.
*/
public static long mysqlRowFixed(int totalCols, int colsAccessed, int numRows) {
return sqliteRowFixed(totalCols, colsAccessed, numRows);
}
// -----------------------------------------------------------------------
// Complexity ratio helper
// -----------------------------------------------------------------------
/** Returns the ratio defective/fixed scan steps for a given configuration. */
public static double complexityRatio(int totalCols, int colsAccessed, int numRows) {
long def = sqliteRowDefective(totalCols, colsAccessed, numRows);
long fix = sqliteRowFixed(totalCols, colsAccessed, numRows);
return (double) def / fix;
}
}