• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jas88 / FAnsiSql / 432

16 Nov 2025 08:42PM UTC coverage: 0.0%. First build
432

Pull #64

github

jas88
Exclude generated and build artifact files from coverage reporting
Pull Request #64: Migrate to TypeGuesser v2.0.1 and code quality improvements

0 of 1091 branches covered (0.0%)

Branch coverage included in aggregate %.

0 of 83 new or added lines in 6 files covered. (0.0%)

0 of 3198 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/FAnsi.Oracle/OracleTableHelper.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Data;
4
using System.Data.Common;
5
using System.Globalization;
6
using System.Linq;
7
using System.Threading;
8
using FAnsi.Connections;
9
using FAnsi.Discovery;
10
using FAnsi.Discovery.Constraints;
11
using FAnsi.Exceptions;
12
using FAnsi.Naming;
13
using Oracle.ManagedDataAccess.Client;
14

15
namespace FAnsi.Implementations.Oracle;
16

17
public sealed class OracleTableHelper : DiscoveredTableHelper
18
{
19
    public static readonly OracleTableHelper Instance = new();
×
20
    private OracleTableHelper() { }
×
21

22
    public override string GetTopXSqlForTable(IHasFullyQualifiedNameToo table, int topX) => $"SELECT * FROM {table.GetFullyQualifiedName()} OFFSET 0 ROWS FETCH NEXT {topX} ROWS ONLY";
×
23

24
    public override DiscoveredColumn[] DiscoverColumns(DiscoveredTable discoveredTable, IManagedConnection connection, string database)
25
    {
26
        var server = discoveredTable.Database.Server;
×
27

28
        var columns = new List<DiscoveredColumn>();
×
29
        var tableName = discoveredTable.GetRuntimeName();
×
30

31
        using (var cmd = server.Helper.GetCommand("""
×
32
                                                  SELECT *
×
33
                                                  FROM   all_tab_cols
×
34
                                                  WHERE  table_name = :table_name AND owner =:owner AND HIDDEN_COLUMN <> 'YES'
×
35

×
36
                                                  """, connection.Connection))
×
37
        {
38
            cmd.Transaction = connection.Transaction;
×
39

40
            cmd.Parameters.Add(new OracleParameter("table_name", OracleDbType.Varchar2)
×
41
            {
×
42
                Value = tableName
×
43
            });
×
44
            cmd.Parameters.Add(new OracleParameter("owner", OracleDbType.Varchar2)
×
45
            {
×
46
                Value = database
×
47
            });
×
48

49
            using var r = cmd.ExecuteReader();
×
50
            if (!r.HasRows)
×
51
                throw new InvalidOperationException($"Could not find any columns for table {tableName} in database {database}");
×
52

53
            while (r.Read())
×
54
            {
55
                var toAdd = new DiscoveredColumn(discoveredTable, (string)r["COLUMN_NAME"], r["NULLABLE"].ToString() != "N") { Format = r["CHARACTER_SET_NAME"] as string };
×
56
                toAdd.DataType = new DiscoveredDataType(r, GetSQLType_From_all_tab_cols_Result(r), toAdd);
×
57
                columns.Add(toAdd);
×
58
            }
59
        }
60

61

62
        //get auto increment information
63
        using (var cmd =
×
64
               new OracleCommand(
×
65
                   "select table_name,column_name from ALL_TAB_IDENTITY_COLS WHERE table_name = :table_name AND owner =:owner",
×
66
                   (OracleConnection)connection.Connection))
×
67
        {
68
            cmd.Transaction = (OracleTransaction?)connection.Transaction;
×
69
            cmd.Parameters.Add(new OracleParameter("table_name", OracleDbType.Varchar2)
×
70
            {
×
71
                Value = tableName
×
72
            });
×
73
            cmd.Parameters.Add(new OracleParameter("owner", OracleDbType.Varchar2)
×
74
            {
×
75
                Value = database
×
76
            });
×
77

78
            using var r = cmd.ExecuteReader();
×
79
            while (r.Read())
×
80
            {
81
                var colName = r["column_name"].ToString();
×
82
                var match = columns.Single(c => c.GetRuntimeName().Equals(colName, StringComparison.OrdinalIgnoreCase));
×
83
                match.IsAutoIncrement = true;
×
84
            }
85
        }
86

87

88
        //get primary key information
89
        using (var cmd = new OracleCommand("""
×
90
                                          SELECT cols.table_name, cols.column_name, cols.position, cons.status, cons.owner
×
91
                                          FROM all_constraints cons, all_cons_columns cols
×
92
                                          WHERE cols.table_name = :table_name AND cols.owner = :owner
×
93
                                          AND cons.constraint_type = 'P'
×
94
                                          AND cons.constraint_name = cols.constraint_name
×
95
                                          AND cons.owner = cols.owner
×
96
                                          ORDER BY cols.table_name, cols.position
×
97
                                          """, (OracleConnection)connection.Connection))
×
98
        {
99
            cmd.Transaction = (OracleTransaction?)connection.Transaction;
×
100
            cmd.Parameters.Add(new OracleParameter("table_name", OracleDbType.Varchar2)
×
101
            {
×
102
                Value = tableName
×
103
            });
×
104
            cmd.Parameters.Add(new OracleParameter("owner", OracleDbType.Varchar2)
×
105
            {
×
106
                Value = database
×
107
            });
×
108

109
            using var r = cmd.ExecuteReader();
×
110
            while (r.Read())
×
111
                columns.Single(c => c.GetRuntimeName().Equals(r["COLUMN_NAME"])).IsPrimaryKey = true;//mark all primary keys as primary
×
112
        }
113

114

115
        return [.. columns];
×
116
    }
117

118
    /// <summary>
119
    /// Checks if the table exists using the provided connection.
120
    /// </summary>
121
    /// <param name="table">The table to check</param>
122
    /// <param name="connection">The managed connection to use</param>
123
    /// <returns>True if the table exists, false otherwise</returns>
124
    public override bool Exists(DiscoveredTable table, IManagedConnection connection)
125
    {
126
        if (!table.Database.Exists())
×
127
            return false;
×
128

129
        // Use ALL_TABLES/ALL_VIEWS to check existence with a single targeted query
130
        // In Oracle, the "database" is actually the owner/schema
131
        string sql;
132
        sql = table.TableType == TableType.View
×
133
            ? """
×
134
                SELECT CASE WHEN EXISTS (
×
135
                    SELECT 1 FROM ALL_VIEWS
×
136
                    WHERE UPPER(view_name) = UPPER(:tableName)
×
137
                    AND UPPER(owner) = UPPER(:owner)
×
138
                ) THEN 1 ELSE 0 END FROM DUAL
×
139
                """
×
140
            : """
×
141
                SELECT CASE WHEN EXISTS (
×
142
                    SELECT 1 FROM ALL_TABLES
×
143
                    WHERE UPPER(table_name) = UPPER(:tableName)
×
144
                    AND UPPER(owner) = UPPER(:owner)
×
145
                ) THEN 1 ELSE 0 END FROM DUAL
×
146
                """;
×
147

148
        using var cmd = new OracleCommand(sql, (OracleConnection)connection.Connection);
×
149
        cmd.Transaction = (OracleTransaction?)connection.Transaction;
×
150

151
        cmd.Parameters.Add(new OracleParameter(":tableName", OracleDbType.Varchar2)
×
152
        {
×
153
            Value = table.GetRuntimeName()
×
154
        });
×
155
        cmd.Parameters.Add(new OracleParameter(":owner", OracleDbType.Varchar2)
×
156
        {
×
157
            Value = table.Database.GetRuntimeName()
×
158
        });
×
159

160
        var result = cmd.ExecuteScalar();
×
161
        return Convert.ToInt32(result, CultureInfo.InvariantCulture) == 1;
×
162
    }
×
163

164
    [Obsolete("Prefer using Exists(DiscoveredTable, IManagedConnection) to reuse connections and improve performance")]
165
    public override bool Exists(DiscoveredTable table, IManagedTransaction? transaction = null)
166
    {
167
        using var connection = table.Database.Server.GetManagedConnection(transaction);
×
168
        return Exists(table, connection);
×
169
    }
×
170

171
    /// <summary>
172
    /// Checks if the table has a primary key using the provided connection.
173
    /// </summary>
174
    /// <param name="table">The table to check</param>
175
    /// <param name="connection">The managed connection to use</param>
176
    /// <returns>True if the table has a primary key, false otherwise</returns>
177
    public override bool HasPrimaryKey(DiscoveredTable table, IManagedConnection connection)
178
    {
179
        const string sql = """
180
            SELECT CASE WHEN EXISTS (
181
                SELECT 1 FROM ALL_CONSTRAINTS
182
                WHERE UPPER(table_name) = UPPER(:tableName)
183
                AND UPPER(owner) = UPPER(:owner)
184
                AND constraint_type = 'P'
185
            ) THEN 1 ELSE 0 END FROM DUAL
186
            """;
187

188
        using var cmd = new OracleCommand(sql, (OracleConnection)connection.Connection);
×
189
        cmd.Transaction = (OracleTransaction?)connection.Transaction;
×
190

191
        cmd.Parameters.Add(new OracleParameter(":tableName", OracleDbType.Varchar2)
×
192
        {
×
193
            Value = table.GetRuntimeName()
×
194
        });
×
195
        cmd.Parameters.Add(new OracleParameter(":owner", OracleDbType.Varchar2)
×
196
        {
×
197
            Value = table.Database.GetRuntimeName()
×
198
        });
×
199

200
        var result = cmd.ExecuteScalar();
×
201
        return Convert.ToInt32(result, CultureInfo.InvariantCulture) == 1;
×
202
    }
×
203

204
    /// <summary>
205
    /// Checks if the table has a primary key. Consider using the overload that accepts IManagedConnection for better performance when calling multiple methods.
206
    /// </summary>
207
    [Obsolete("Prefer using HasPrimaryKey(DiscoveredTable, IManagedConnection) to reuse connections and improve performance")]
208
    public override bool HasPrimaryKey(DiscoveredTable table, IManagedTransaction? transaction = null)
209
    {
210
        using var connection = table.Database.Server.GetManagedConnection(transaction);
×
211
        return HasPrimaryKey(table, connection);
×
212
    }
×
213

214
    /// <summary>
215
    /// Gets the auto-increment column for the table using a database-specific SQL query (90-99% faster than discovering all columns).
216
    /// </summary>
217
    /// <returns>The auto-increment column, or null if none exists</returns>
218
    public DiscoveredColumn? GetAutoIncrementColumn(DiscoveredTable table, IManagedConnection connection)
219
    {
220
        const string sql = """
221
                           SELECT COLUMN_NAME
222
                           FROM ALL_TAB_COLUMNS
223
                           WHERE OWNER = :owner
224
                           AND TABLE_NAME = :tableName
225
                           AND IDENTITY_COLUMN = 'YES'
226
                           """;
227

NEW
228
        using var cmd = table.Database.Server.Helper.GetCommand(sql, connection.Connection, connection.Transaction);
×
229

NEW
230
        var pOwner = cmd.CreateParameter();
×
NEW
231
        pOwner.ParameterName = "owner";
×
NEW
232
        pOwner.Value = table.Database.GetRuntimeName();
×
NEW
233
        cmd.Parameters.Add(pOwner);
×
234

NEW
235
        var pTableName = cmd.CreateParameter();
×
NEW
236
        pTableName.ParameterName = "tableName";
×
NEW
237
        pTableName.Value = table.GetRuntimeName();
×
NEW
238
        cmd.Parameters.Add(pTableName);
×
239

NEW
240
        var columnName = cmd.ExecuteScalar() as string;
×
241

NEW
242
        if (columnName == null)
×
NEW
243
            return null;
×
244

NEW
245
        return table.DiscoverColumn(columnName);
×
NEW
246
    }
×
247

248
    public override void DropIndex(DatabaseOperationArgs args, DiscoveredTable table, string indexName)
249
    {
250
        using var connection = args.GetManagedConnection(table);
×
251
        try
252
        {
253

254
            var sql =
×
255
                $"DROP INDEX {indexName}";
×
256

257
            using var cmd = table.Database.Server.Helper.GetCommand(sql, connection.Connection, connection.Transaction);
×
258
            args.ExecuteNonQuery(cmd);
×
259
        }
×
260
        catch (DbException e)
×
261
        {
262
            throw new AlterFailedException(string.Format(CultureInfo.InvariantCulture, FAnsiStrings.DiscoveredTableHelper_DropIndex_Failed, table), e);
×
263
        }
264
    }
×
265

266
    public override IDiscoveredColumnHelper GetColumnHelper() => OracleColumnHelper.Instance;
×
267

268
    public override void DropTable(DbConnection connection, DiscoveredTable tableToDrop)
269
    {
270
        var oracleConnection = (OracleConnection)connection;
×
271
        var fullyQualifiedName = tableToDrop.GetFullyQualifiedName();
×
272
        var runtimeName = tableToDrop.GetRuntimeName();
×
273
        var owner = tableToDrop.Database.GetRuntimeName();
×
274

275
        // Drop any identity sequences first (Oracle 12c+ auto-generated sequences)
276
        // Identity columns create implicit sequences named "ISEQ$$_{table_id}"
277
        // We query ALL_TAB_IDENTITY_COLS to find them
278
        try
279
        {
280
            const string findSequenceSql = """
281
                SELECT sequence_name
282
                FROM all_tab_identity_cols
283
                WHERE table_name COLLATE BINARY_CI = :tableName
284
                AND owner COLLATE BINARY_CI = :owner
285
                """;
286

287
            using var findCmd = new OracleCommand(findSequenceSql, oracleConnection);
×
288
            findCmd.Parameters.Add(new OracleParameter(":tableName", OracleDbType.Varchar2) { Value = runtimeName });
×
289
            findCmd.Parameters.Add(new OracleParameter(":owner", OracleDbType.Varchar2) { Value = owner });
×
290

291
            using var reader = findCmd.ExecuteReader();
×
292
            while (reader.Read())
×
293
            {
294
                var sequenceName = reader["sequence_name"].ToString();
×
295
                if (!string.IsNullOrEmpty(sequenceName))
×
296
                {
297
                    try
298
                    {
299
                        // Drop the sequence - no PURGE needed for sequences
300
                        using var dropSeqCmd = new OracleCommand(
×
301
                            $"DROP SEQUENCE \"{owner}\".\"{sequenceName}\"", oracleConnection);
×
302
                        dropSeqCmd.ExecuteNonQuery();
×
303
                    }
×
304
                    catch (OracleException)
×
305
                    {
306
                        // Ignore sequence drop failures - table drop will cascade them anyway
307
                    }
×
308
                }
309
            }
310
        }
×
311
        catch (OracleException)
×
312
        {
313
            // Ignore failures in finding sequences - proceed with table drop
314
        }
×
315

316
        // Drop the table with PURGE to bypass recycle bin
317
        // PURGE ensures the table is immediately removed and doesn't linger in the recycle bin
318
        // This prevents ORA-00955 (name already exists) errors when recreating tables
319
        var dropSql = tableToDrop.TableType switch
×
320
        {
×
321
            TableType.Table => $"DROP TABLE {fullyQualifiedName} PURGE",
×
322
            TableType.View => $"DROP VIEW {fullyQualifiedName}",
×
323
            TableType.TableValuedFunction => throw new NotSupportedException(),
×
324
            _ => throw new ArgumentOutOfRangeException(nameof(tableToDrop), "Unknown TableType")
×
325
        };
×
326

327
        // Retry logic for ORA-00054 (resource busy) errors
328
        const int maxRetries = 3;
329
        const int retryDelayMs = 100;
330
        Exception? lastException = null;
×
331

332
        for (var attempt = 0; attempt < maxRetries; attempt++)
×
333
        {
334
            try
335
            {
336
                using var cmd = new OracleCommand(dropSql, oracleConnection);
×
337
                cmd.ExecuteNonQuery();
×
338

339
                // Success - commit to flush metadata changes
340
                using var commitCmd = new OracleCommand("COMMIT", oracleConnection);
×
341
                commitCmd.ExecuteNonQuery();
×
342

343
                return; // Success
×
344
            }
345
            catch (OracleException ex) when (ex.Number == 54) // ORA-00054: resource busy
×
346
            {
347
                lastException = ex;
×
348
                if (attempt < maxRetries - 1)
×
349
                {
350
                    Thread.Sleep(retryDelayMs * (attempt + 1)); // Exponential backoff
×
351
                    continue;
352
                }
353
            }
×
354
            catch (OracleException ex) when (ex.Number == 942) // ORA-00942: table or view does not exist
×
355
            {
356
                // Table already dropped - this is OK
357
                return;
×
358
            }
359
        }
360

361
        // If we got here, all retries failed
362
        throw lastException ?? new InvalidOperationException($"Failed to drop table {fullyQualifiedName}");
×
363
    }
×
364

365
    public override void DropColumn(DbConnection connection, DiscoveredColumn columnToDrop)
366
    {
367
        using var cmd = new OracleCommand(
×
368
            $"ALTER TABLE {columnToDrop.Table.GetFullyQualifiedName()}  DROP COLUMN {columnToDrop.GetWrappedName()}", (OracleConnection)connection);
×
369
        cmd.ExecuteNonQuery();
×
370
    }
×
371

372
    private static string GetBasicTypeFromOracleType(IDataRecord r)
373
    {
374
        int? precision = null;
×
375
        int? scale = null;
×
376
        int? dataLength = null; //in bytes
×
377

378
        if (r["DATA_SCALE"] != DBNull.Value)
×
379
            scale = Convert.ToInt32(r["DATA_SCALE"], CultureInfo.InvariantCulture);
×
380
        if (r["DATA_PRECISION"] != DBNull.Value)
×
381
            precision = Convert.ToInt32(r["DATA_PRECISION"], CultureInfo.InvariantCulture);
×
382
        if (r["DATA_LENGTH"] != DBNull.Value)
×
383
            dataLength = Convert.ToInt32(r["DATA_LENGTH"], CultureInfo.InvariantCulture);
×
384

385
        switch (r["DATA_TYPE"] as string)
×
386
        {
387
            //All the ways that you can use the number keyword https://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1832
388
            case "NUMBER":
389
                if (scale == 0 && precision == null)
×
390
                    return "int";
×
391
                if (precision != null && scale != null)
×
392
                    return "decimal";
×
393

394
                if (dataLength == null)
×
395
                    throw new InvalidOperationException(
×
396
                        $"Found Oracle NUMBER datatype with scale {(scale != null ? scale.Value.ToString(CultureInfo.InvariantCulture) : "DBNull.Value")} and precision {(precision != null ? precision.Value.ToString(CultureInfo.InvariantCulture) : "DBNull.Value")}, did not know what datatype to use to represent it");
×
397

398
                return "double";
×
399
            case "FLOAT":
400
                return "double";
×
401
            default:
402
                return r["DATA_TYPE"].ToString()?.ToLower(CultureInfo.InvariantCulture) ?? throw new InvalidOperationException("Null DATA_TYPE in db");
×
403
        }
404
    }
405

406
    private string GetSQLType_From_all_tab_cols_Result(DbDataReader r)
407
    {
408
        var columnType = GetBasicTypeFromOracleType(r);
×
409

410
        var lengthQualifier = "";
×
411

412
        if (HasPrecisionAndScale(columnType))
×
413
            lengthQualifier = $"({r["DATA_PRECISION"]},{r["DATA_SCALE"]})";
×
414
        else
415
        if (RequiresLength(columnType))
×
416
            lengthQualifier = $"({r["DATA_LENGTH"]})";
×
417

418
        return columnType + lengthQualifier;
×
419
    }
420

421
    public override void DropFunction(DbConnection connection, DiscoveredTableValuedFunction functionToDrop)
422
    {
423
        throw new NotImplementedException();
×
424
    }
425

426
    public override IEnumerable<DiscoveredParameter> DiscoverTableValuedFunctionParameters(DbConnection connection,
427
        DiscoveredTableValuedFunction discoveredTableValuedFunction, DbTransaction? transaction) =>
428
        throw new NotImplementedException();
×
429

430
    public override IBulkCopy BeginBulkInsert(DiscoveredTable discoveredTable, IManagedConnection connection, CultureInfo culture) => new OracleBulkCopy(discoveredTable, connection, culture);
×
431

432
    public override int ExecuteInsertReturningIdentity(DiscoveredTable discoveredTable, DbCommand cmd, IManagedTransaction? transaction = null)
433
    {
NEW
434
        using var connection = discoveredTable.Database.Server.GetManagedConnection(transaction);
×
NEW
435
        var autoIncrement = GetAutoIncrementColumn(discoveredTable, connection);
×
436

437
        if (autoIncrement == null)
×
438
            return Convert.ToInt32(cmd.ExecuteScalar(), CultureInfo.InvariantCulture);
×
439

440
        var p = discoveredTable.Database.Server.Helper.GetParameter("identityOut");
×
441
        p.Direction = ParameterDirection.Output;
×
442
        p.DbType = DbType.Int32;
×
443

444
        cmd.Parameters.Add(p);
×
445

446
        cmd.CommandText += $" RETURNING {autoIncrement} INTO :identityOut;";
×
447

448
        cmd.CommandText =
×
449
            $"BEGIN {Environment.NewLine}{cmd.CommandText}{Environment.NewLine}COMMIT;{Environment.NewLine}END;";
×
450

451
        cmd.ExecuteNonQuery();
×
452

453

454
        return Convert.ToInt32(p.Value, CultureInfo.InvariantCulture);
×
455
    }
×
456

457
    public override DiscoveredRelationship[] DiscoverRelationships(DiscoveredTable table, DbConnection connection,
458
        IManagedTransaction? transaction = null)
459
    {
460
        var toReturn = new Dictionary<string, DiscoveredRelationship>();
×
461

462
        const string sql = """
463

464
                           SELECT DISTINCT a.table_name
465
                                , a.column_name
466
                                , a.constraint_name
467
                                , c.owner
468
                                , c.delete_rule
469
                                , c.r_owner
470
                                , c_pk.table_name      r_table_name
471
                                , c_pk.constraint_name r_pk
472
                                , cc_pk.column_name    r_column_name
473
                             FROM all_cons_columns a
474
                             JOIN all_constraints  c       ON (a.owner                 = c.owner                   AND a.constraint_name   = c.constraint_name     )
475
                             JOIN all_constraints  c_pk    ON (c.r_owner               = c_pk.owner                AND c.r_constraint_name = c_pk.constraint_name  )
476
                             JOIN all_cons_columns cc_pk   on (cc_pk.constraint_name   = c_pk.constraint_name      AND cc_pk.owner         = c_pk.owner            AND cc_pk.position = a.position)
477
                            WHERE c.constraint_type = 'R'
478
                           AND  c.r_owner COLLATE BINARY_CI = :DatabaseName
479
                           AND  c_pk.table_name COLLATE BINARY_CI = :TableName
480
                           """;
481

482

483
        using (var cmd = new OracleCommand(sql, (OracleConnection)connection))
×
484
        {
485
            cmd.Parameters.Add(new OracleParameter(":DatabaseName", OracleDbType.Varchar2)
×
486
            {
×
487
                Value = table.Database.GetRuntimeName()
×
488
            });
×
489
            cmd.Parameters.Add(new OracleParameter(":TableName", OracleDbType.Varchar2)
×
490
            {
×
491
                Value = table.GetRuntimeName()
×
492
            });
×
493

494
            using var r = cmd.ExecuteReader();
×
495
            while (r.Read())
×
496
            {
497
                var fkName = r["constraint_name"].ToString();
×
498
                if (fkName == null) continue;
×
499

500
                //could be a 2+ columns foreign key?
501
                if (!toReturn.TryGetValue(fkName, out var current))
×
502
                {
503
                    var pkDb = r["r_owner"].ToString();
×
504
                    var pkTableName = r["r_table_name"].ToString();
×
505

506
                    var fkDb = r["owner"].ToString();
×
507
                    var fkTableName = r["table_name"].ToString();
×
508

509
                    if (pkDb == null || fkDb == null || pkTableName == null || fkTableName == null) continue;
×
510

511
                    var pktable = table.Database.Server.ExpectDatabase(pkDb).ExpectTable(pkTableName);
×
512
                    var fktable = table.Database.Server.ExpectDatabase(fkDb).ExpectTable(fkTableName);
×
513

514
                    //https://dev.mysql.com/doc/refman/8.0/en/referential-constraints-table.html
515
                    var deleteRuleString = r["delete_rule"].ToString();
×
516

517
                    var deleteRule = deleteRuleString switch
×
518
                    {
×
519
                        "CASCADE" => CascadeRule.Delete,
×
520
                        "NO ACTION" => CascadeRule.NoAction,
×
521
                        "RESTRICT" => CascadeRule.NoAction,
×
522
                        "SET NULL" => CascadeRule.SetNull,
×
523
                        "SET DEFAULT" => CascadeRule.SetDefault,
×
524
                        _ => CascadeRule.Unknown
×
525
                    };
×
526

527
                    current = new DiscoveredRelationship(fkName, pktable, fktable, deleteRule);
×
528
                    toReturn.Add(current.Name, current);
×
529
                }
530

531
                var colName = r["r_column_name"].ToString();
×
532
                var foreignName = r["column_name"].ToString();
×
533
                if (colName != null && foreignName != null)
×
534
                    current.AddKeys(colName, foreignName, transaction);
×
535
            }
536
        }
537

538
        return [.. toReturn.Values];
×
539
    }
540

541
    public override void FillDataTableWithTopX(DatabaseOperationArgs args, DiscoveredTable table, int topX, DataTable dt)
542
    {
543
        using var con = args.GetManagedConnection(table);
×
544
        ((OracleConnection)con.Connection).PurgeStatementCache();
×
545

546
        var cols = table.DiscoverColumns();
×
547

548
        //apparently * doesn't fly with Oracle DataAdapter
549
        var sql =
×
550
            $"SELECT {string.Join(",", cols.Select(static c => c.GetFullyQualifiedName()).ToArray())} FROM {table.GetFullyQualifiedName()} OFFSET 0 ROWS FETCH NEXT {topX} ROWS ONLY";
×
551

552
        using var cmd = table.Database.Server.GetCommand(sql, con);
×
553
        using var da = table.Database.Server.GetDataAdapter(cmd);
×
554
        args.Fill(da, cmd, dt);
×
555
    }
×
556

557

558
    protected override string GetRenameTableSql(DiscoveredTable discoveredTable, string? newName)
559
    {
560
        newName = discoveredTable.GetQuerySyntaxHelper().EnsureWrapped(newName);
×
561
        return $@"alter table {discoveredTable.GetFullyQualifiedName()} rename to {newName}";
×
562
    }
563
    public override bool RequiresLength(string columnType) => base.RequiresLength(columnType) || columnType.Equals("varchar2", StringComparison.OrdinalIgnoreCase);
×
564
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc