/// <summary> /// Given all arguments for package's procs, load all package specific types (e.g., a record) into memory /// </summary> /// <param name="arguments"></param> private void LoadPackageRecordTypes <T_PackageRecord, T_Field, T_Argument>(List <IArgument> arguments) where T_PackageRecord : class, IPackageRecord, new() where T_Field : class, IField, new() where T_Argument : class, IArgument, new() { foreach (IArgument arg in arguments) { switch (arg.DataType) { case Orcl.RECORD: if (arg.DataLevel == 0) { continue; // ignore straight record type (without cursor) } // send the record argument and a list of all subsequent arguments LoadRecordType <T_PackageRecord, T_Field, T_Argument>(arg, arguments.GetRange(arguments.IndexOf(arg) + 1, arguments.Count - arguments.IndexOf(arg) - 1), null); continue; case Orcl.ASSOCIATITVE_ARRAY: // For an associative array of a record, we will need to create a class for the record. if (arguments[arguments.IndexOf(arg) + 1].DataType == Orcl.RECORD) { // First get type of the associated array by converting to C#. This will be a list of a class. We need the class name // in order to to load into our Oracle record types. String assocArrayCSharpType = Translater.ConvertOracleArgTypeToCSharpType(arg, false); // Send the arg following the assoc array arg since it holds the record, a list of all args following the record arg, // and the C# name of the record parsed out of the assoc array C# type. LoadRecordType <T_PackageRecord, T_Field, T_Argument>(arguments[arguments.IndexOf(arg) + 1], arguments.GetRange(arguments.IndexOf(arg) + 2, arguments.Count - arguments.IndexOf(arg) - 2), CSharp.ExtractSubtypeFromGenericCollectionType(assocArrayCSharpType, false)); } continue; default: continue; } } return; }
/// <summary> /// Given a record type argument, extract and store the record type and its fields (recurse if necessary) /// </summary> /// <param name="recordArg">Argument with record</param> /// <param name="args">List of arguments following record argument</param> private void LoadRecordType <T_PackageRecord, T_Field, T_Argument>(IArgument recordArg, List <IArgument> args, String cSharpType) where T_PackageRecord : class, IPackageRecord, new() where T_Field : class, IField, new() where T_Argument : class, IArgument, new() { if (recordArg.DataType != Orcl.RECORD) { throw new Exception("Argument sent to LoadRecordType() that is not a PL/SQL RECORD"); } // happens for type OBJECT, TABLE, VARRAY or UNDEFINED if ((recordArg.TypeName == null && recordArg.TypeSubname != null) || (recordArg.TypeName != null && recordArg.TypeSubname == null)) { return; } if (cSharpType == null) { cSharpType = Translater.ConvertOracleArgTypeToCSharpType(recordArg, false); } // if the record type has already been stored, do not proceeed if (PackageRecordTypes.Any(r => (r.SubName ?? "") == (recordArg.TypeSubname ?? "") && (r.Name ?? "") == (recordArg.TypeName ?? "") && (r.Owner ?? "") == (recordArg.TypeOwner ?? "") && (r.PackageName ?? "") == (recordArg.PackageName ?? ""))) { return; } // begin creation of record type IPackageRecord newRec = new T_PackageRecord(); newRec.PackageName = recordArg.PackageName; // package containing argument newRec.Name = recordArg.TypeName; // package containing *record type* newRec.SubName = recordArg.TypeSubname; // name of record type if outside argument's package newRec.CSharpType = cSharpType; newRec.Owner = recordArg.TypeOwner; newRec.Attributes = new List <IEntityAttribute>(); int recordDataLevel = recordArg.DataLevel; // loop the args to find this record's fields or a nested record type int columnPosition = 0; foreach (IArgument arg in args) { if (arg.DataLevel == recordDataLevel + 1) // found a record field // each of these fields are to be added to the record { IField f = new T_Field(); f.Name = arg.ArgumentName; // convert to C# now - this should to be adjusted so it's done later f.CSharpType = Translater.ConvertOracleArgTypeToCSharpType(arg, false); // set the containing class from the package name if (!String.IsNullOrEmpty(arg.TypeName) && !arg.TypeName.Equals(arg.PackageName)) { if (!Parameter.Instance.IsDuplicatePackageRecordOriginatingOutsideFilterAndSchema // owned by another schema or owned by package that was filtered out && (!(arg.Owner ?? "").Equals(arg.TypeOwner) // || !_packages.Exists(p => p.PackageName.Equals(arg.TypeName)) ) ) { || !Packages.Any(p => p.PackageName.Equals(arg.TypeName)))) { f.ContainerClassName = Translater.ConvertOracleNameToCSharpName(arg.TypeName, false); } if (!(arg.TypeName ?? "").Equals(arg.PackageName) // && _packages.Exists(p => p.PackageName.Equals(arg.TypeName)) // package of origin of record being created && Packages.Any(p => p.PackageName.Equals(arg.TypeName)) && // package of origin of record being created PackageRecordTypes.Exists(r => r.PackageName.Equals(arg.TypeName) && r.SubName.Equals(arg.TypeSubname))) { f.ContainerClassName = Translater.ConvertOracleNameToCSharpName(arg.TypeName, false); } } f.AttrType = arg.DataType; f.Length = arg.DataLength; f.Precision = arg.DataPrecision; f.Scale = arg.DataScale; f.MapPosition = columnPosition++; newRec.Attributes.Add(f); } else if (arg.DataLevel == recordDataLevel + 2) // found a lower level field, so skip { continue; } else if (arg.DataLevel <= recordDataLevel) // we are past the last record field, we are done { break; } // if field is nested record, recurse into it if (arg.DataType == Orcl.RECORD) { LoadRecordType <T_PackageRecord, T_Field, T_Argument>(arg, args.GetRange(args.IndexOf(arg) + 1, args.Count - args.IndexOf(arg) - 1), null); } } // newRec.Fields.Sort(); PackageRecordTypes.Add(newRec); return; }