iridium_core 0.1.12

SQL Server-compatible Rust engine core for Iridium SQL
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
use super::common::{lower_data_type, lower_expr, lower_object_name};
use super::dml::lower_select;
use super::lower_statement;
use crate::ast as executor_ast;
use crate::error::DbError;
use crate::parser::ast;

pub fn lower_procedural(
    proc: ast::ProceduralStatement,
) -> Result<executor_ast::Statement, DbError> {
    match proc {
        ast::ProceduralStatement::Declare(vars) => {
            if vars.len() == 1 {
                let var = match vars.into_iter().next() {
                    Some(var) => var,
                    None => {
                        return Err(DbError::Parse(
                            "DECLARE requires at least one variable".into(),
                        ))
                    }
                };
                Ok(executor_ast::Statement::Procedural(
                    executor_ast::statements::ProceduralStatement::Declare(
                        executor_ast::statements::procedural::DeclareStmt {
                            name: var.name,
                            data_type: lower_data_type(var.data_type)?,
                            default: var.initial_value.map(lower_expr).transpose()?,
                        },
                    ),
                ))
            } else {
                let mut stmts = Vec::new();
                for var in vars {
                    stmts.push(executor_ast::Statement::Procedural(
                        executor_ast::statements::ProceduralStatement::Declare(
                            executor_ast::statements::procedural::DeclareStmt {
                                name: var.name,
                                data_type: lower_data_type(var.data_type)?,
                                default: var.initial_value.map(lower_expr).transpose()?,
                            },
                        ),
                    ));
                }
                Ok(executor_ast::Statement::Procedural(
                    executor_ast::statements::ProceduralStatement::BeginEnd(stmts),
                ))
            }
        }
        ast::ProceduralStatement::DeclareTableVar {
            name,
            columns,
            constraints,
        } => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::DeclareTableVar(
                executor_ast::statements::procedural::DeclareTableVarStmt {
                    name,
                    columns: columns
                        .into_iter()
                        .map(super::ddl::lower_column_def)
                        .collect::<Result<Vec<_>, _>>()?,
                    table_constraints: constraints
                        .into_iter()
                        .map(super::ddl::lower_table_constraint)
                        .collect::<Result<Vec<_>, _>>()?,
                },
            ),
        )),
        ast::ProceduralStatement::Synonym { name, base_object } => Ok(
            executor_ast::Statement::Ddl(executor_ast::statements::DdlStatement::CreateSynonym(
                executor_ast::statements::ddl::CreateSynonymStmt {
                    name: lower_object_name(name),
                    base_object: lower_object_name(base_object),
                },
            )),
        ),
        ast::ProceduralStatement::Sequence {
            name,
            data_type,
            start_with,
            increment_by,
            min_value,
            max_value,
            cycle,
        } => Ok(executor_ast::Statement::Ddl(
            executor_ast::statements::DdlStatement::CreateSequence(
                executor_ast::statements::ddl::CreateSequenceStmt {
                    name: lower_object_name(name),
                    data_type: data_type
                        .map(lower_data_type)
                        .transpose()?
                        .unwrap_or(executor_ast::data_types::DataTypeSpec::BigInt),
                    start_value: start_with.unwrap_or(1),
                    increment: increment_by.unwrap_or(1),
                    minimum_value: min_value.unwrap_or(i64::MIN),
                    maximum_value: max_value.unwrap_or(i64::MAX),
                    is_cycling: cycle,
                },
            ),
        )),
        ast::ProceduralStatement::DeclareCursor { name, query } => {
            Ok(executor_ast::Statement::Procedural(
                executor_ast::statements::ProceduralStatement::DeclareCursor(
                    executor_ast::statements::procedural::DeclareCursorStmt {
                        name,
                        query: lower_select(query)?,
                    },
                ),
            ))
        }
        ast::ProceduralStatement::Set { variable, expr } => {
            Ok(executor_ast::Statement::Procedural(
                executor_ast::statements::ProceduralStatement::Set(
                    executor_ast::statements::procedural::SetStmt {
                        name: variable,
                        expr: lower_expr(expr)?,
                    },
                ),
            ))
        }
        ast::ProceduralStatement::If {
            condition,
            then_stmt,
            else_stmt,
        } => {
            let then_body = match lower_statement(*then_stmt)? {
                executor_ast::Statement::Procedural(
                    executor_ast::statements::ProceduralStatement::BeginEnd(stmts),
                ) => stmts,
                other => vec![other],
            };
            let else_body = match else_stmt {
                Some(s) => Some(match lower_statement(*s)? {
                    executor_ast::Statement::Procedural(
                        executor_ast::statements::ProceduralStatement::BeginEnd(stmts),
                    ) => stmts,
                    other => vec![other],
                }),
                None => None,
            };
            Ok(executor_ast::Statement::Procedural(
                executor_ast::statements::ProceduralStatement::If(
                    executor_ast::statements::procedural::IfStmt {
                        condition: lower_expr(condition)?,
                        then_body,
                        else_body,
                    },
                ),
            ))
        }
        ast::ProceduralStatement::BeginEnd(stmts) => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::BeginEnd(
                stmts
                    .into_iter()
                    .map(lower_statement)
                    .collect::<Result<Vec<_>, _>>()?,
            ),
        )),
        ast::ProceduralStatement::While { condition, stmt } => {
            let body = match lower_statement(*stmt)? {
                executor_ast::Statement::Procedural(
                    executor_ast::statements::ProceduralStatement::BeginEnd(stmts),
                ) => stmts,
                other => vec![other],
            };
            Ok(executor_ast::Statement::Procedural(
                executor_ast::statements::ProceduralStatement::While(
                    executor_ast::statements::procedural::WhileStmt {
                        condition: lower_expr(condition)?,
                        body,
                    },
                ),
            ))
        }
        ast::ProceduralStatement::Break => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::Break,
        )),
        ast::ProceduralStatement::Continue => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::Continue,
        )),
        ast::ProceduralStatement::Return(expr) => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::Return(
                expr.map(lower_expr).transpose()?,
            ),
        )),
        ast::ProceduralStatement::Print(expr) => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::Print(lower_expr(expr)?),
        )),
        ast::ProceduralStatement::Raiserror {
            message,
            severity,
            state,
        } => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::Raiserror(
                executor_ast::statements::procedural::RaiserrorStmt {
                    message: lower_expr(message)?,
                    severity: lower_expr(severity)?,
                    state: lower_expr(state)?,
                },
            ),
        )),
        ast::ProceduralStatement::Throw {
            error_number,
            message,
            state,
        } => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::Throw(
                executor_ast::statements::procedural::ThrowStmt {
                    error_number: error_number.map(lower_expr).transpose()?,
                    message: message.map(lower_expr).transpose()?,
                    state: state.map(lower_expr).transpose()?,
                },
            ),
        )),
        ast::ProceduralStatement::TryCatch {
            try_body,
            catch_body,
        } => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::TryCatch(
                executor_ast::statements::procedural::TryCatchStmt {
                    try_body: try_body
                        .into_iter()
                        .map(lower_statement)
                        .collect::<Result<Vec<_>, _>>()?,
                    catch_body: catch_body
                        .into_iter()
                        .map(lower_statement)
                        .collect::<Result<Vec<_>, _>>()?,
                },
            ),
        )),
        ast::ProceduralStatement::ExecDynamic { sql_expr } => {
            Ok(executor_ast::Statement::Procedural(
                executor_ast::statements::ProceduralStatement::ExecDynamic(
                    executor_ast::statements::procedural::ExecStmt {
                        sql_expr: lower_expr(sql_expr)?,
                    },
                ),
            ))
        }
        ast::ProceduralStatement::ExecProcedure {
            return_variable,
            name,
            args,
        } => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::ExecProcedure(
                executor_ast::statements::procedural::ExecProcedureStmt {
                    return_variable,
                    name: lower_object_name(name),
                    args: args
                        .into_iter()
                        .map(lower_exec_arg)
                        .collect::<Result<Vec<_>, _>>()?,
                },
            ),
        )),
        ast::ProceduralStatement::SpExecuteSql {
            sql_expr,
            params_def,
            args,
        } => Ok(executor_ast::Statement::Procedural(
            executor_ast::statements::ProceduralStatement::SpExecuteSql(
                executor_ast::statements::procedural::SpExecuteSqlStmt {
                    sql_expr: lower_expr(sql_expr)?,
                    params_def: params_def.map(lower_expr).transpose()?,
                    args: args
                        .into_iter()
                        .map(lower_exec_arg)
                        .collect::<Result<Vec<_>, _>>()?,
                },
            ),
        )),
    }
}

pub fn lower_transaction(
    txn: ast::TransactionStatement,
) -> Result<executor_ast::Statement, DbError> {
    match txn {
        ast::TransactionStatement::Begin(name) => Ok(executor_ast::Statement::Transaction(
            executor_ast::statements::TransactionStatement::Begin(name),
        )),
        ast::TransactionStatement::Commit(name) => Ok(executor_ast::Statement::Transaction(
            executor_ast::statements::TransactionStatement::Commit(name),
        )),
        ast::TransactionStatement::Rollback(name) => Ok(executor_ast::Statement::Transaction(
            executor_ast::statements::TransactionStatement::Rollback(name),
        )),
        ast::TransactionStatement::Save(name) => Ok(executor_ast::Statement::Transaction(
            executor_ast::statements::TransactionStatement::Save(name),
        )),
    }
}

pub fn lower_cursor(cursor: ast::CursorStatement) -> Result<executor_ast::Statement, DbError> {
    match cursor {
        ast::CursorStatement::Open(name) => Ok(executor_ast::Statement::Cursor(
            executor_ast::statements::CursorStatement::OpenCursor(name),
        )),
        ast::CursorStatement::Fetch {
            name,
            direction,
            into_vars,
        } => Ok(executor_ast::Statement::Cursor(
            executor_ast::statements::CursorStatement::FetchCursor(
                executor_ast::statements::procedural::FetchCursorStmt {
                    name,
                    direction: lower_fetch_direction(direction)?,
                    into: into_vars,
                },
            ),
        )),
        ast::CursorStatement::Close(name) => Ok(executor_ast::Statement::Cursor(
            executor_ast::statements::CursorStatement::CloseCursor(name),
        )),
        ast::CursorStatement::Deallocate(name) => Ok(executor_ast::Statement::Cursor(
            executor_ast::statements::CursorStatement::DeallocateCursor(name),
        )),
    }
}

pub fn lower_session(session: ast::SessionStatement) -> Result<executor_ast::Statement, DbError> {
    match session {
        ast::SessionStatement::SetTransactionIsolationLevel(iso) => {
            Ok(executor_ast::Statement::Session(
                executor_ast::statements::SessionStatement::SetTransactionIsolationLevel(
                    match iso {
                        ast::IsolationLevel::ReadUncommitted => {
                            executor_ast::IsolationLevel::ReadUncommitted
                        }
                        ast::IsolationLevel::ReadCommitted => {
                            executor_ast::IsolationLevel::ReadCommitted
                        }
                        ast::IsolationLevel::RepeatableRead => {
                            executor_ast::IsolationLevel::RepeatableRead
                        }
                        ast::IsolationLevel::Serializable => {
                            executor_ast::IsolationLevel::Serializable
                        }
                        ast::IsolationLevel::Snapshot => executor_ast::IsolationLevel::Snapshot,
                    },
                ),
            ))
        }
        ast::SessionStatement::UseDatabase(database) => Ok(executor_ast::Statement::Session(
            executor_ast::statements::SessionStatement::UseDatabase(database),
        )),
        ast::SessionStatement::SetOption { option, value } => Ok(executor_ast::Statement::Session(
            executor_ast::statements::SessionStatement::SetOption(
                executor_ast::statements::procedural::SetOptionStmt {
                    option: match option {
                        ast::SessionOption::AnsiNulls => executor_ast::SessionOption::AnsiNulls,
                        ast::SessionOption::QuotedIdentifier => {
                            executor_ast::SessionOption::QuotedIdentifier
                        }
                        ast::SessionOption::NoCount => executor_ast::SessionOption::NoCount,
                        ast::SessionOption::XactAbort => executor_ast::SessionOption::XactAbort,
                        ast::SessionOption::FmtOnly => executor_ast::SessionOption::FmtOnly,
                        ast::SessionOption::NoExec => executor_ast::SessionOption::NoExec,
                        ast::SessionOption::DateFirst => executor_ast::SessionOption::DateFirst,
                        ast::SessionOption::Language => executor_ast::SessionOption::Language,
                        ast::SessionOption::DateFormat => executor_ast::SessionOption::DateFormat,
                        ast::SessionOption::LockTimeout => executor_ast::SessionOption::LockTimeout,
                        ast::SessionOption::RowCount => executor_ast::SessionOption::RowCount,
                        ast::SessionOption::TextSize => executor_ast::SessionOption::TextSize,
                        ast::SessionOption::ConcatNullYieldsNull => {
                            executor_ast::SessionOption::ConcatNullYieldsNull
                        }
                        ast::SessionOption::ArithAbort => executor_ast::SessionOption::ArithAbort,
                        ast::SessionOption::QueryGovernorCostLimit => {
                            executor_ast::SessionOption::QueryGovernorCostLimit
                        }
                        ast::SessionOption::DeadlockPriority => {
                            executor_ast::SessionOption::DeadlockPriority
                        }
                        ast::SessionOption::AnsiNullDfltOn => {
                            executor_ast::SessionOption::AnsiNullDfltOn
                        }
                        ast::SessionOption::AnsiPadding => executor_ast::SessionOption::AnsiPadding,
                        ast::SessionOption::AnsiWarnings => {
                            executor_ast::SessionOption::AnsiWarnings
                        }
                        ast::SessionOption::CursorCloseOnCommit => {
                            executor_ast::SessionOption::CursorCloseOnCommit
                        }
                        ast::SessionOption::ImplicitTransactions => {
                            executor_ast::SessionOption::ImplicitTransactions
                        }
                        ast::SessionOption::StatisticsIo => {
                            executor_ast::SessionOption::StatisticsIo
                        }
                        ast::SessionOption::StatisticsTime => {
                            executor_ast::SessionOption::StatisticsTime
                        }
                        ast::SessionOption::ShowplanAll => executor_ast::SessionOption::ShowplanAll,
                        ast::SessionOption::AnsiDefaults => {
                            executor_ast::SessionOption::AnsiDefaults
                        }
                        ast::SessionOption::Unsupported(v) => {
                            executor_ast::SessionOption::Unsupported(v)
                        }
                    },
                    value: match value {
                        ast::SessionOptionValue::Bool(v) => {
                            executor_ast::SessionOptionValue::Bool(v)
                        }
                        ast::SessionOptionValue::Int(v) => executor_ast::SessionOptionValue::Int(v),
                        ast::SessionOptionValue::Text(v) => {
                            executor_ast::SessionOptionValue::Text(v)
                        }
                    },
                },
            ),
        )),
        ast::SessionStatement::SetIdentityInsert { table, on } => {
            Ok(executor_ast::Statement::Session(
                executor_ast::statements::SessionStatement::SetIdentityInsert(
                    executor_ast::statements::SetIdentityInsertStmt {
                        table: lower_object_name(table),
                        on,
                    },
                ),
            ))
        }
        ast::SessionStatement::SetContextInfo(expr) => Ok(executor_ast::Statement::Session(
            executor_ast::statements::SessionStatement::SetContextInfo(lower_expr(expr)?),
        )),
    }
}

pub fn lower_exec_arg(
    a: ast::ExecArg,
) -> Result<executor_ast::statements::procedural::ExecArgument, DbError> {
    Ok(executor_ast::statements::procedural::ExecArgument {
        name: a.name,
        expr: lower_expr(a.expr)?,
        is_output: a.is_output,
    })
}

pub fn lower_fetch_direction(
    d: ast::FetchDirection,
) -> Result<executor_ast::statements::procedural::FetchDirection, DbError> {
    match d {
        ast::FetchDirection::Next => Ok(executor_ast::statements::procedural::FetchDirection::Next),
        ast::FetchDirection::Prior => {
            Ok(executor_ast::statements::procedural::FetchDirection::Prior)
        }
        ast::FetchDirection::First => {
            Ok(executor_ast::statements::procedural::FetchDirection::First)
        }
        ast::FetchDirection::Last => Ok(executor_ast::statements::procedural::FetchDirection::Last),
        ast::FetchDirection::Absolute(expr) => {
            Ok(executor_ast::statements::procedural::FetchDirection::Absolute(lower_expr(expr)?))
        }
        ast::FetchDirection::Relative(expr) => {
            Ok(executor_ast::statements::procedural::FetchDirection::Relative(lower_expr(expr)?))
        }
    }
}