public void UpdateArgumentsOracleTest()
        {
            //arrange
            var converter = new SchemaProcedureConverter();
            var schema = new DatabaseSchema(null, null);
            #region deserialize datatable
            //from Oracle HR. Captured from var datatable.WriteXml(StringWriter)
            const string data = @"<DocumentElement>
  <ProcedureParameters>
    <Schema>HR</Schema>
    <Procedure>GET_CURRENT_TIME</Procedure>
    <Name>P_DATE</Name>
    <Position>1</Position>
    <Sequence>1</Sequence>
    <DataType>DATE</DataType>
    <Direction>IN/OUT</Direction>
  </ProcedureParameters>
  <ProcedureParameters>
    <Schema>HR</Schema>
    <Procedure>ADD_JOB_HISTORY</Procedure>
    <Name>P_EMP_ID</Name>
    <Position>1</Position>
    <Sequence>1</Sequence>
    <DataType>NUMBER</DataType>
    <Direction>IN</Direction>
    <Length>22</Length>
    <Precision>6</Precision>
  </ProcedureParameters>
  <ProcedureParameters>
    <Schema>HR</Schema>
    <Procedure>ADD_JOB_HISTORY</Procedure>
    <Name>P_START_DATE</Name>
    <Position>2</Position>
    <Sequence>2</Sequence>
    <DataType>DATE</DataType>
    <Direction>IN</Direction>
  </ProcedureParameters>
  <ProcedureParameters>
    <Schema>HR</Schema>
    <Procedure>ADD_JOB_HISTORY</Procedure>
    <Name>P_END_DATE</Name>
    <Position>3</Position>
    <Sequence>3</Sequence>
    <DataType>DATE</DataType>
    <Direction>IN</Direction>
  </ProcedureParameters>
  <ProcedureParameters>
    <Schema>HR</Schema>
    <Procedure>ADD_JOB_HISTORY</Procedure>
    <Name>P_JOB_ID</Name>
    <Position>4</Position>
    <Sequence>4</Sequence>
    <DataType>VARCHAR2</DataType>
    <Direction>IN</Direction>
    <Length>10</Length>
    <Charset>CHAR_CS</Charset>
  </ProcedureParameters>
  <ProcedureParameters>
    <Schema>HR</Schema>
    <Procedure>ADD_JOB_HISTORY</Procedure>
    <Name>P_DEPARTMENT_ID</Name>
    <Position>5</Position>
    <Sequence>5</Sequence>
    <DataType>NUMBER</DataType>
    <Direction>IN</Direction>
    <Length>22</Length>
    <Precision>4</Precision>
  </ProcedureParameters>
</DocumentElement>
";
            var sr = new StringReader(data);
            var ds = new DataSet();
            ds.ReadXml(sr);
            var dataTable = ds.Tables[0];
            #endregion

            //act
            converter.UpdateArguments(schema, dataTable);

            //assert
            var sprocs = schema.StoredProcedures;
            Assert.AreEqual(2, sprocs.Count);

            var addHistory = sprocs.Find(x => x.Name == "ADD_JOB_HISTORY");
            Assert.AreEqual(5, addHistory.Arguments.Count);
            var empId = addHistory.Arguments.Find(x => x.Name == "P_EMP_ID");
            Assert.AreEqual(1, empId.Ordinal);
            Assert.AreEqual("NUMBER", empId.DatabaseDataType);
            Assert.AreEqual(true, empId.In);
            Assert.AreEqual(false, empId.Out);


            var currentTime = sprocs.Find(x => x.Name == "GET_CURRENT_TIME");
            var date = currentTime.Arguments.Find(x => x.Name == "P_DATE");
            Assert.AreEqual(1, date.Ordinal);
            Assert.AreEqual("DATE", date.DatabaseDataType);
            //inout type!
            Assert.AreEqual(true, date.In);
            Assert.AreEqual(true, date.Out);
        }
        /// <summary>
        /// Gets all stored procedures (and functions) with their arguments
        /// </summary>
        /// <remarks>
        /// <para>We also get the source (if available)</para>
        /// <para>We don't get functions here.</para>
        /// <para>In Oracle stored procedures are often in packages. We read the non-packaged stored procedures, then add packaged stored procedures if they have arguments. If they don't have arguments, they are not found.</para>
        /// </remarks>
        public IList<DatabaseStoredProcedure> AllStoredProcedures()
        {
            try
            {
                DataTable functions = _schemaReader.Functions();
                DatabaseSchema.Functions.Clear();
                DatabaseSchema.Functions.AddRange(SchemaProcedureConverter.Functions(functions));
            }
            catch (DbException ex)
            {
                Debug.WriteLine("Cannot read functions - database security may prevent access to DDL\n" + ex.Message);
                throw; //or suppress if not applicable
            }

            DataTable dt = _schemaReader.StoredProcedures();
            SchemaProcedureConverter.StoredProcedures(DatabaseSchema, dt);
            var procFilter = Exclusions.StoredProcedureFilter;
            if (procFilter != null)
            {
                DatabaseSchema.StoredProcedures.RemoveAll(p => procFilter.Exclude(p.Name));
            }

            DatabaseSchema.Packages.Clear();
            DatabaseSchema.Packages.AddRange(SchemaProcedureConverter.Packages(_schemaReader.Packages()));
            var packFilter = Exclusions.PackageFilter;
            if (packFilter != null)
            {
                DatabaseSchema.Packages.RemoveAll(p => packFilter.Exclude(p.Name));
            }
            //do all the arguments as one call and sort them out.
            //NB: This is often slow on Oracle
            DataTable args = _schemaReader.StoredProcedureArguments(null);

            var converter = new SchemaProcedureConverter();
            converter.PackageFilter = Exclusions.PackageFilter;
            converter.StoredProcedureFilter = Exclusions.StoredProcedureFilter;
            if (args.Rows.Count == 0)
            {
                //MySql v6 won't do all stored procedures. So we have to do them individually.
                foreach (var sproc in DatabaseSchema.StoredProcedures)
                {
                    args = _schemaReader.StoredProcedureArguments(sproc.Name);
                    converter.UpdateArguments(DatabaseSchema, args);
                }

                foreach (var function in DatabaseSchema.Functions)
                {
                    args = _schemaReader.StoredProcedureArguments(function.Name);
                    converter.UpdateArguments(DatabaseSchema, args);
                }
            }
            //arguments could be for functions too
            converter.UpdateArguments(DatabaseSchema, args);
            foreach (var function in DatabaseSchema.Functions)
            {
                //return types are assigned as arguments (in most platforms). Move them to return type.
                function.CheckArgumentsForReturnType();
            }

            //procedure, function and view source sql
            DataTable srcs = _schemaReader.ProcedureSource(null);
            SchemaSourceConverter.AddSources(DatabaseSchema, srcs);

            UpdateReferences();

            return DatabaseSchema.StoredProcedures;
        }
        public void UpdateArgumentsSqlServerTest()
        {
            //arrange
            var converter = new SchemaProcedureConverter();
            var schema = new DatabaseSchema(null, null);
            #region deserialize datatable
            //from SqlServer Northwind. Captured from var datatable.WriteXml(StringWriter)
            const string data = @"<DocumentElement>
  <ProcedureParameters>
    <SPECIFIC_CATALOG>Northwind</SPECIFIC_CATALOG>
    <SPECIFIC_SCHEMA>dbo</SPECIFIC_SCHEMA>
    <SPECIFIC_NAME>GetWeekDay</SPECIFIC_NAME>
    <ORDINAL_POSITION>0</ORDINAL_POSITION>
    <PARAMETER_MODE>OUT</PARAMETER_MODE>
    <IS_RESULT>YES</IS_RESULT>
    <AS_LOCATOR>NO</AS_LOCATOR>
    <PARAMETER_NAME />
    <DATA_TYPE>int</DATA_TYPE>
    <NUMERIC_PRECISION>10</NUMERIC_PRECISION>
    <NUMERIC_PRECISION_RADIX>10</NUMERIC_PRECISION_RADIX>
    <NUMERIC_SCALE>0</NUMERIC_SCALE>
  </ProcedureParameters>
  <ProcedureParameters>
    <SPECIFIC_CATALOG>Northwind</SPECIFIC_CATALOG>
    <SPECIFIC_SCHEMA>dbo</SPECIFIC_SCHEMA>
    <SPECIFIC_NAME>GetWeekDay</SPECIFIC_NAME>
    <ORDINAL_POSITION>1</ORDINAL_POSITION>
    <PARAMETER_MODE>IN</PARAMETER_MODE>
    <IS_RESULT>NO</IS_RESULT>
    <AS_LOCATOR>NO</AS_LOCATOR>
    <PARAMETER_NAME>@Date</PARAMETER_NAME>
    <DATA_TYPE>datetime</DATA_TYPE>
    <DATETIME_PRECISION>3</DATETIME_PRECISION>
  </ProcedureParameters>
  <ProcedureParameters>
    <SPECIFIC_CATALOG>Northwind</SPECIFIC_CATALOG>
    <SPECIFIC_SCHEMA>dbo</SPECIFIC_SCHEMA>
    <SPECIFIC_NAME>GetCurrentDate</SPECIFIC_NAME>
    <ORDINAL_POSITION>1</ORDINAL_POSITION>
    <PARAMETER_MODE>INOUT</PARAMETER_MODE>
    <IS_RESULT>NO</IS_RESULT>
    <AS_LOCATOR>NO</AS_LOCATOR>
    <PARAMETER_NAME>@p1</PARAMETER_NAME>
    <DATA_TYPE>datetime2</DATA_TYPE>
    <DATETIME_PRECISION>7</DATETIME_PRECISION>
  </ProcedureParameters>
  <ProcedureParameters>
    <SPECIFIC_CATALOG>Northwind</SPECIFIC_CATALOG>
    <SPECIFIC_SCHEMA>dbo</SPECIFIC_SCHEMA>
    <SPECIFIC_NAME>Sales by Year</SPECIFIC_NAME>
    <ORDINAL_POSITION>1</ORDINAL_POSITION>
    <PARAMETER_MODE>IN</PARAMETER_MODE>
    <IS_RESULT>NO</IS_RESULT>
    <AS_LOCATOR>NO</AS_LOCATOR>
    <PARAMETER_NAME>@Beginning_Date</PARAMETER_NAME>
    <DATA_TYPE>datetime</DATA_TYPE>
    <DATETIME_PRECISION>3</DATETIME_PRECISION>
  </ProcedureParameters>
  <ProcedureParameters>
    <SPECIFIC_CATALOG>Northwind</SPECIFIC_CATALOG>
    <SPECIFIC_SCHEMA>dbo</SPECIFIC_SCHEMA>
    <SPECIFIC_NAME>Sales by Year</SPECIFIC_NAME>
    <ORDINAL_POSITION>2</ORDINAL_POSITION>
    <PARAMETER_MODE>IN</PARAMETER_MODE>
    <IS_RESULT>NO</IS_RESULT>
    <AS_LOCATOR>NO</AS_LOCATOR>
    <PARAMETER_NAME>@Ending_Date</PARAMETER_NAME>
    <DATA_TYPE>datetime</DATA_TYPE>
    <DATETIME_PRECISION>3</DATETIME_PRECISION>
  </ProcedureParameters>
</DocumentElement>";
            var sr = new StringReader(data);
            var ds = new DataSet();
            ds.ReadXml(sr);
            var dataTable = ds.Tables[0];
            #endregion

            //act
            converter.UpdateArguments(schema, dataTable);

            //assert
            var sprocs = schema.StoredProcedures;
            Assert.AreEqual(2, sprocs.Count); //function GetWeekDay is ignored
            Assert.AreEqual(1, schema.Functions.Count); //here's where GetWeekDay is

            var salesByYear = sprocs.Find(x => x.Name == "Sales by Year");
            Assert.AreEqual(2, salesByYear.Arguments.Count);
            var date = salesByYear.Arguments.Find(x => x.Name == "@Beginning_Date");
            Assert.AreEqual(1, date.Ordinal);
            Assert.AreEqual("datetime", date.DatabaseDataType);
            Assert.AreEqual(true, date.In);
            Assert.AreEqual(false, date.Out);


            var currentTime = sprocs.Find(x => x.Name == "GetCurrentDate");
            Assert.AreEqual(1, currentTime.Arguments.Count);
            var p1 = currentTime.Arguments.Find(x => x.Name == "@p1");
            Assert.AreEqual(1, p1.Ordinal);
            Assert.AreEqual("datetime2", p1.DatabaseDataType);
            //in-out type!
            Assert.AreEqual(true, p1.In);
            Assert.AreEqual(true, p1.Out);

            var fun = schema.Functions[0];
            Assert.AreEqual("int", fun.ReturnType);
            Assert.AreEqual(1, fun.Arguments.Count); //even though we had 2 in the data table
            var input = fun.Arguments[0];
            Assert.AreEqual("@Date", input.Name);
            Assert.AreEqual("datetime", input.DatabaseDataType);
            Assert.AreEqual(true, input.In);

        }
 public override IList<DatabaseArgument> ProcedureArguments(string name)
 {
     var dt = _schemaReader.StoredProcedureArguments(name);
     var converter = new SchemaProcedureConverter
     {
         PackageFilter = Parameters.Exclusions.PackageFilter,
         StoredProcedureFilter = Parameters.Exclusions.StoredProcedureFilter
     };
     return converter.Arguments(dt);
 }