Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/ts_generator/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ pub enum TsGeneratorError {
TableFactorWhileProcessingTableWithJoins(String),
#[error("[E014] Failed to find a table name from a FROM statement: statement: `{0}`")]
UnknownErrorWhileProcessingTableWithJoins(String),
#[error("[E015] Table expressions are not supported in INSERT statements - query: `{0}`")]
TableExpressionInInsertStatement(String),
#[error("[E016] Column '{column}' not found in table '{table}'. Available columns: {available_columns}")]
ColumnNotFoundInTable {
column: String,
table: String,
available_columns: String,
},
#[error("[E017] Failed to process INSERT statement: {reason}. Query: `{query}`")]
InsertStatementProcessingFailed { reason: String, query: String },
#[error("[E018] Table '{table}' not found in database schema. Check that the table exists and is accessible.")]
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two different error variants are using the same error code [E018]. The TableNotFoundInSchema error on line 47 and UpdateStatementProcessingFailed error on line 45 both use [E018]. One should be changed to [E020] or another unique code to avoid confusion.

Suggested change
#[error("[E018] Table '{table}' not found in database schema. Check that the table exists and is accessible.")]
#[error("[E020] Table '{table}' not found in database schema. Check that the table exists and is accessible.")]

Copilot uses AI. Check for mistakes.
TableNotFoundInSchema { table: String },
#[error("[E019] Failed to infer table name while processing WHERE clause. Query: `{query}`")]
Comment thread
JasonShin marked this conversation as resolved.
Outdated
TableNameInferenceFailedInWhere { query: String },
Comment thread
JasonShin marked this conversation as resolved.
Outdated
#[error(
"[E020] Invalid column reference '{column}' for table '{table}'. Ensure the column exists in the table schema."
)]
InvalidColumnReference { column: String, table: String },
#[error("Unknown error: `{0}`")]
Unknown(String),
}
4 changes: 2 additions & 2 deletions src/ts_generator/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ pub fn write_single_ts_file(sqls_to_write: String) -> Result<()> {
))?;

let parent_output_path: Option<&Path> = output.parent();
if parent_output_path.is_some() {
fs::create_dir_all(parent_output_path.unwrap())?;
if let Some(parent_output_path) = parent_output_path {
fs::create_dir_all(parent_output_path)?;
}

let mut file_to_write = OpenOptions::new()
Expand Down
68 changes: 52 additions & 16 deletions src/ts_generator/sql_parser/expressions/translate_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,11 @@ pub async fn get_sql_query_param(
} else if single_table_name.is_some() {
table_name = single_table_name.map(|x| x.to_string());
} else {
panic!("failed to find an appropriate table name while processing WHERE statement")
error!(
"Failed to infer table name while processing WHERE clause. Expression: {}",
left
);
return None;
Comment thread
JasonShin marked this conversation as resolved.
Outdated
}

let column_name = translate_column_name_expr(left);
Expand All @@ -144,17 +148,30 @@ pub async fn get_sql_query_param(
match (column_name, expr_placeholder, table_name) {
(Some(column_name), Some(expr_placeholder), Some(table_name)) => {
let table_names = vec![table_name.as_str()];
let columns = DB_SCHEMA
.lock()
.await
.fetch_table(&table_names, db_conn)
.await
.unwrap_or_else(|| panic!("Failed to fetch columns for table {table_name}"));
let columns = DB_SCHEMA.lock().await.fetch_table(&table_names, db_conn).await;

if columns.is_none() {
error!(
"Table '{}' not found in database schema. Check that the table exists and is accessible.",
table_name
);
return None;
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error logs a message but returns None instead of propagating an error. The caller won't be able to distinguish this failure from a legitimate None case. Consider returning TsGeneratorError::TableNotFoundInSchema which is already defined in errors.rs.

Copilot uses AI. Check for mistakes.
Comment thread
JasonShin marked this conversation as resolved.
Outdated
}

let columns = columns.unwrap();

// get column and return TsFieldType
let column = columns
.get(column_name.as_str())
.unwrap_or_else(|| panic!("Failed to find the column from the table schema of {table_name}"));
let column = columns.get(column_name.as_str());
if column.is_none() {
let available_columns = columns.keys().map(|k| k.as_str()).collect::<Vec<_>>().join(", ");
error!(
"Column '{}' not found in table '{}'. Available columns: {}",
column_name, table_name, available_columns
);
return None;
Comment thread
JasonShin marked this conversation as resolved.
Outdated
Comment thread
JasonShin marked this conversation as resolved.
Outdated
}

let column = column.unwrap();
Some((column.field_type.to_owned(), column.is_nullable, Some(expr_placeholder)))
}
_ => None,
Expand Down Expand Up @@ -731,16 +748,35 @@ pub async fn translate_assignment(
let value = get_expr_placeholder(&assignment.value);

if value.is_some() {
let table_details = &DB_SCHEMA
let table_details = DB_SCHEMA
Comment thread
JasonShin marked this conversation as resolved.
.lock()
.await
.fetch_table(&vec![table_name], db_conn)
.await
.unwrap();
let column_name = translate_column_name_assignment(assignment).unwrap();
let field = table_details
.get(&column_name)
.unwrap_or_else(|| panic!("Failed to find the column detail for {column_name}"));
.ok_or_else(|| TsGeneratorError::TableNotFoundInSchema {
table: table_name.to_string(),
})?;

let column_name = translate_column_name_assignment(assignment).ok_or_else(|| {
TsGeneratorError::InsertStatementProcessingFailed {
reason: "Failed to extract column name from assignment".to_string(),
query: format!("UPDATE {} SET {} = ...", table_name, assignment),
}
})?;
Comment on lines +757 to +762
Copy link

Copilot AI Dec 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error uses InsertStatementProcessingFailed for an UPDATE statement scenario. This is misleading as the error variant name suggests it's for INSERT operations, but it's being used in translate_assignment which handles UPDATE statements. Consider creating a new error variant like UpdateStatementProcessingFailed or renaming the existing variant to something more generic like StatementProcessingFailed.

Copilot uses AI. Check for mistakes.

let field = table_details.get(&column_name).ok_or_else(|| {
let available_columns = table_details
.keys()
.map(|k| k.as_str())
.collect::<Vec<_>>()
.join(", ");
TsGeneratorError::ColumnNotFoundInTable {
column: column_name.clone(),
table: table_name.to_string(),
available_columns,
}
})?;

let _ = ts_query.insert_param(&field.field_type, &field.is_nullable, &value);
}
Ok(())
Expand Down
47 changes: 30 additions & 17 deletions src/ts_generator/sql_parser/translate_insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,32 @@ pub async fn translate_insert(
if placeholder.is_some() {
let match_col = &columns
.get(column)
.unwrap_or_else(|| {
panic!(
r#"
Failed to process values of insert statement as column names are not provided or incorrectly specified

Try specifying column names
```
INSERT INTO table_name (column1, column2, column3, ...)
VALUES (value1, value2, value3, ...);
```
"#
)
})
.ok_or_else(|| {
TsGeneratorError::InsertStatementProcessingFailed {
reason: format!(
"Column at position {} is not provided in the column list. Expected {} columns but found {} values.",
column, columns.len(), values.len()
Comment thread
JasonShin marked this conversation as resolved.
),
query: format!(
"INSERT INTO {} VALUES (...). Try specifying column names explicitly: INSERT INTO {} (column1, column2, ...) VALUES (...)",
table_name, table_name
),
}
})?
.value;

let field = table_details
.get(match_col.as_str())
.unwrap_or_else(|| panic!("Column {match_col} is not found while processing insert params"));
let field = table_details.get(match_col.as_str()).ok_or_else(|| {
let available_columns = table_details
.keys()
.map(|k| k.as_str())
.collect::<Vec<_>>()
.join(", ");
TsGeneratorError::ColumnNotFoundInTable {
column: match_col.clone(),
table: table_name.to_string(),
available_columns,
}
})?;

if value.to_string() == "?" {
// If the placeholder is `'?'`, we can process it using insert_value_params and generate nested params type
Expand Down Expand Up @@ -104,7 +112,12 @@ VALUES (value1, value2, value3, ...);
SetExpr::Update(update) => translate_stmt(ts_query, &update, None, conn).await?,
SetExpr::Delete(delete) => translate_stmt(ts_query, &delete, None, conn).await?,
SetExpr::Merge(merge) => translate_stmt(ts_query, &merge, None, conn).await?,
SetExpr::Table(_) => unimplemented!("Table expressions are not supported in INSERT statements"),
SetExpr::Table(table) => {
return Err(TsGeneratorError::TableExpressionInInsertStatement(format!(
"INSERT INTO {} ... FROM {}",
table_name, table
)));
}
}

Ok(())
Expand Down
8 changes: 6 additions & 2 deletions src/ts_generator/sql_parser/translate_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,12 @@ pub async fn translate_select(
let mut table_name: Option<&str> = None;
if full_table_with_joins.is_some() && !full_table_with_joins.as_ref().unwrap().is_empty() {
table_name_owned = Some(
translate_table_with_joins(full_table_with_joins, &select_item)
.unwrap_or_else(|_| panic!("{}", format!("Default FROM table is not found from the query {select}"))),
translate_table_with_joins(full_table_with_joins, &select_item).map_err(|_| {
TsGeneratorError::UnknownErrorWhileProcessingTableWithJoins(format!(
"Default FROM table is not found from the query: {}. Ensure your query has a valid FROM clause.",
select
))
})?,
);
table_name = table_name_owned.as_deref();
}
Expand Down
Loading