#!/usr/bin/env qore
# -*- mode: qore; indent-tabs-mode: nil -*-

%new-style
%enable-all-warnings
%require-types
%strict-args

%requires ../../../../qlib/Util.qm
%requires ../../../../qlib/QUnit.qm
%requires ../../../../qlib/Logger.qm
%requires ../../../../qlib/DataProvider
%requires ../../../../qlib/SqlUtil
%requires ../../../../qlib/BulkSqlUtil
%requires ../../../../qlib/OracleSqlUtil.qm
%requires ../../../../qlib/Schema.qm

%requires ./BulkSqlUtilTestBase.qm
#/;
%try-module oracle
%define NoOracle
%endtry

%exec-class OracleTest

class OracleTestSchema inherits SqlUtilTestSchema {
    public {
        const SchemaName = "OracleTestSchema";
        const SchemaVersion = "1.0";
    }

    private {
        const GenericOptions = (
            "replace": True,
        );

        const IndexOptions = {};

        const ColumnOptions = {};

        const T_OracleTest = (
            "columns": (
                "id": c_number(14, True, "an example comment with 'quotes'"),
                "id_": c_number(14, True),
                "null_f": c_varchar(69),
            ),
            "primary_key": ("name": "pk_oracle_test", "columns": ("id")),
        );

        const Tables = (
            "oracle_test": T_OracleTest,
        );

        const Sequences = (
            "oracle_test_seq": {},
        );
    }

    constructor(AbstractDatasource ds, *string dts, *string its) : SqlUtilTestSchema(ds, dts, its) {
    }

    private string getNameImpl() {
        return SchemaName;
    }

    private string getVersionImpl() {
        return SchemaVersion;
    }

    private *hash getTablesImpl() {
        return doTables(Tables, OracleTest::CustomColumns + OracleTest::ConstColumns);
    }

    private *hash getSequencesImpl() {
        return Sequences;
    }

    private *hash getIndexOptionsImpl() {
        return IndexOptions;
    }

    private *hash getGenericOptionsImpl() {
        return GenericOptions;
    }

    private *hash getColumnOptionsImpl() {
        return ColumnOptions;
    }
}

class OracleTest inherits SqlTestBase {
    public {
        const CustomColumns = (
            "varchar2": (
                "value": "hello",
                "size": 20,
            ),
            "char": (
                "value": "hello",
                "size": 20,
                "expect": rpad("hello", 20),
            ),
            "number": (
                "size": 15,
                "scale": 2,
                "value": 400.95n,
            ),
            "number_def": (
                "type": "number",
                "value": 400.95n,
            ),
            "date": 2016-01-11,
            "timestamp": 2016-01-11T09:26:14.502134,
            # why are the timestamp with * time zone tests failing during DST?
            #"timestamp with time zone": 2016-01-11T09:26:14.502134,
            #"timestamp with local time zone": 2016-01-11T09:26:14.502134,
            #"interval year to month": 2Y + 6M,
            #"interval day to second": 2D + 3h + 4m + 1s,
            "clob": "test",
            "blob": <bead>,
            "binary_float": 1.5,
            "binary_double": 1.5,
            #raw
            #bfile
            #long
        );

        const ConstColumns = (
            "const_f": (
                "type": "varchar2",
                "value": "test",
                "size": "20",
            ),
        );
    }

    constructor() : SqlTestBase("OracleTest", "1.0", \ARGV, MyOpts) {
        Datasource ds;
        try {
            ds = getDatasource();
        } catch (hash<ExceptionInfo> ex) {
            if (m_options.verbose)
                printf("%s: %s\n", ex.err, ex.desc);
            # skip tests if we can't create the datasource
        }

        if (ds) {
            initTestData(CustomColumns, ConstColumns);

            { # Make sure the DB is clear before doing the tests.
                OracleTable t = new OracleTable(ds, "oracle_test");
                if (t.checkExistence())
                    t.dropCommit();
            }

            # create the test schema
            schema = new OracleTestSchema(ds);

            schema.align(False, m_options.verbose, m_options.verbose > 0);

            # get table object
            table = (new Table(schema.getDatasource(), "oracle_test")).getTable();
        }

        set_return_value(main());
    }

    private usageIntern() {
        TestReporter::usageIntern(OptionColumn);
        printOption("-c,--conn=ARG", "set DB connection argument (ex: \"oracle:user/pass@db\")", OptionColumn);
    }

    Datasource getDatasource() {
        if (!m_options.connstr)
            m_options.connstr = ENV.QORE_DB_CONNSTR_ORACLE;
        Datasource ds(m_options.connstr);
        if (ds.getDriverName() != "oracle")
            throw "ORACLE-ERROR", sprintf("cannot execute the oracle tests on a connection using driver %y", ds.getDriverName());
        ds.open();
        return ds;
    }
}
