2 using System.Collections.Generic;
5 using Newtonsoft.Json.Linq;
15 BYTES =
Avro.EnumSchema.Type.Bytes,
16 DOUBLE =
Avro.EnumSchema.Type.Double,
17 FLOAT =
Avro.EnumSchema.Type.Float,
18 INT =
Avro.EnumSchema.Type.Int,
19 LONG =
Avro.EnumSchema.Type.Long,
20 STRING =
Avro.EnumSchema.Type.String,
21 DEFAULT =
Avro.EnumSchema.Type.Error
24 private string m_name;
26 private bool m_isNullable;
27 private IList<string> m_properties;
40 m_properties = properties ??
new List<string>();
49 public string getName() {
return m_name; }
69 internal void setIsNullable(
bool val ) { m_isNullable = val; }
96 private void initialize()
98 if (
string.IsNullOrEmpty(m_name))
100 throw new ArgumentException(
"Name must not be empty.");
114 throw new ArgumentException(
"Column " + m_name +
" must be of type BYTES, DOUBLE, FLOAT, INT, LONG or STRING.");
117 foreach (var it
in m_properties)
119 if (
string.IsNullOrEmpty(it))
121 throw new ArgumentException(
"Properties must not be empty.");
133 return $
"{m_name} ({m_type.ToString()})";
137 private class TypeData
140 public IList<Column> columns =
new List<Column>();
141 public Dictionary<string, int> columnMap =
new Dictionary<string, int>();
142 public string schemaString = null;
143 public Schema schema = null;
144 public Type sourceType = null;
147 private TypeData m_data =
new TypeData();
148 private IDictionary<string, IList<string>> m_properties =
new Dictionary<string, IList<string>>();
149 private string m_type_id = null;
159 var response = kinetica.
showTable(tableName);
160 var typeIdCount = response.
type_ids.Count;
162 if (typeIdCount == 0)
167 string typeID = response.type_ids[0];
170 for (
int i = 1; i < typeIdCount; ++i)
172 if (response.type_ids[i] != typeID)
179 return new KineticaType(response.type_labels[0], response.type_schemas[0], response.properties[0], typeID );
190 var response = kinetica.
showTypes(typeId,
"");
192 if (response.type_ids.Count < 1)
197 return new KineticaType(response.labels[0], response.type_schemas[0], response.properties[0]);
209 Object[] column_headers, Object[] column_types )
212 if ( column_headers.Length != column_types.Length )
213 throw new KineticaException(
"List of column names and types are not of the same length." );
216 JObject dynamic_schema_json;
219 dynamic_schema_json = JObject.Parse( dynamic_table_schema_string );
221 catch ( Exception ex )
229 var is_column_nulllable =
new Func<string, JObject, bool>( (column_name, schema_json) => {
231 bool found_field =
false;
232 foreach ( var field
in schema_json[
"fields"] )
234 if ( (
string)field[
"name" ] == column_name )
240 var type_element = field[
"type"][
"items"];
241 if ( type_element is JValue )
244 if ( (type_element is JArray) && ((string)((JArray)type_element)[ 1 ] ==
"null") )
250 throw new KineticaException( $
"Could not find the field named '{column_name}'" );
256 IList<Column> columns =
new List<Column>();
257 IDictionary<string, IList<string>> column_properties =
new Dictionary<string, IList<string>>();
258 for (
int i = 0; i < column_headers.Length; ++i )
261 string column_name = column_headers[ i ].
ToString();
265 string column_type_string = column_types[ i ].ToString();
269 IList<string> column_property =
new List<string>();
275 switch ( column_type_string )
298 column_property.Add( column_type_string );
310 column_property.Add( column_type_string );
321 column_property.Add( column_type_string );
340 throw new KineticaException(
"Unknown data type/property: " + column_type_string );
344 if ( is_column_nulllable( $
"column_{i + 1}", dynamic_schema_json ) )
349 Column column =
new Column( column_name, column_type, column_property );
350 columns.Add( column );
353 column_properties.Add( column_name, column_property );
358 return new KineticaType(
"", columns, column_properties );
380 return fromClass( recordClass,
"", properties );
393 public static KineticaType fromClass( Type recordClass,
string label, IDictionary<
string, IList<string>> properties = null )
397 System.Reflection.PropertyInfo[] type_properties = recordClass.GetProperties(
System.Reflection.BindingFlags.DeclaredOnly |
398 System.Reflection.BindingFlags.Instance |
399 System.Reflection.BindingFlags.Public );
400 Array.Sort( type_properties, delegate (
System.Reflection.PropertyInfo p1,
System.Reflection.PropertyInfo p2 )
401 { return p1.MetadataToken.CompareTo( p2.MetadataToken ); } );
404 List<Column> columns =
new List<Column>();
405 List<string> column_names =
new List<string>();
408 foreach ( var property
in type_properties )
410 string column_name =
"";
412 IList<string> column_properties = null;
413 bool is_column_nullable =
false;
416 column_name =
property.Name;
418 Type prop_type =
property.PropertyType;
421 if ( property.PropertyType.IsGenericType &&
422 ( property.PropertyType.GetGenericTypeDefinition() == typeof( Nullable<> ) ) )
424 is_column_nullable =
true;
426 prop_type = Nullable.GetUnderlyingType( prop_type );
430 if ( prop_type == typeof(
System.String ) )
434 else if ( prop_type == typeof(
System.Int32 ) )
438 else if ( prop_type == typeof(
System.Int64 ) )
442 else if ( prop_type == typeof(
float ) )
446 else if ( prop_type == typeof(
double ) )
450 else if ( prop_type == typeof( byte ) )
457 " (must be one of int, long, float, double, string, and byte)" );
460 if ( properties != null )
463 properties.TryGetValue( column_name, out column_properties );
467 column_names.Add( column_name );
470 Column column =
new Column( column_name, column_type, column_properties );
471 if ( is_column_nullable )
472 column.setIsNullable(
true );
475 columns.Add( column );
479 if ( properties != null )
481 IEnumerable<string> property_keys = properties.Keys;
482 var unknown_columns = property_keys.Where( e => !column_names.Contains( e ) );
484 if ( unknown_columns.Any() )
508 return fromObject( recordObj,
"", properties );
521 public static KineticaType fromObject(Object recordObj,
string label =
"", IDictionary<
string, IList<string>> properties = null)
526 Type object_type = recordObj.GetType();
528 return fromClass( object_type, label, properties );
537 m_data.columns = columns;
547 public KineticaType(
string label, IList<Column> columns) : this(columns)
549 m_data.label = label;
558 public KineticaType(
string label, IList<Column> columns, IDictionary<
string, IList<string>> properties ) : this( label, columns )
560 m_properties = properties ??
new Dictionary<string, IList<string>>();
569 m_data.schemaString = typeSchema;
570 createSchemaFromString( typeSchema );
581 public KineticaType(
string label,
string typeSchema, IDictionary<
string, IList<string>> properties,
string typeID = null )
583 m_properties = properties;
585 m_data.label = label;
586 m_data.schemaString = typeSchema;
587 createSchemaFromString(typeSchema, properties);
597 public bool hasColumn(
string name) {
return m_data.columnMap.ContainsKey(name); }
608 this.m_data.sourceType = sourceType;
622 if ( this.m_data.sourceType != null )
636 private void initialize()
638 int columnCount = m_data.columns.Count;
640 if (columnCount == 0)
642 throw new ArgumentException(
"At least one column must be specified.");
645 for (
int i = 0; i < columnCount; ++i)
647 string columnName = m_data.columns[i].getName();
649 if (m_data.columnMap.ContainsKey(columnName))
651 throw new ArgumentException(
"Duplicate column name " + columnName +
" specified.");
654 m_data.columnMap[columnName] = i;
664 private void createSchemaFromString(
string typeSchema,
665 IDictionary<
string, IList<string>> properties = null)
670 m_data.schema = RecordSchema.Parse(typeSchema);
677 var root = JObject.Parse(typeSchema);
679 var rootType = root[
"type"];
680 if ((null == rootType) || !rootType.ToString().Contains(
"record"))
682 throw new ArgumentException(
"Schema must be of type record.");
685 var fields = root[
"fields"];
686 if ((null == fields) || !fields.HasValues)
688 throw new ArgumentException(
"Schema has no fields.");
691 foreach (var field
in fields)
699 var fieldName = (string) field[
"name"];
700 if (
string.IsNullOrEmpty(fieldName))
702 throw new ArgumentException(
"Schema has unnamed field.");
705 if (m_data.columnMap.ContainsKey(fieldName))
707 throw new ArgumentException($
"Duplicate field name {fieldName}.");
710 var fieldType = field[
"type"];
711 if (null == fieldType)
713 throw new ArgumentException($
"Field {fieldName} has no type.");
717 bool is_column_nullable =
false;
719 if (fieldType.HasValues)
721 var fieldTypeArray = fieldType;
723 foreach (var fieldTypeElement
in fieldTypeArray.Children())
728 var fieldTypeElementString = fieldTypeElement.ToString();
730 if (!
string.IsNullOrEmpty(fieldTypeElementString))
732 if (fieldTypeElementString ==
"null" || fieldTypeElementString ==
"\"null\"")
734 is_column_nullable =
true;
739 fieldType = fieldTypeElement;
747 throw new ArgumentException(
"Field {fieldName} has invalid type.");
759 if (fieldType.ToString().Equals(
"bytes") || fieldType.ToString().Equals(
"\"bytes\""))
763 else if (fieldType.ToString().Equals(
"double") || fieldType.ToString().Equals(
"\"double\""))
767 else if (fieldType.ToString().Equals(
"float") || fieldType.ToString().Equals(
"\"float\""))
771 else if (fieldType.ToString().Equals(
"int") || fieldType.ToString().Equals(
"\"int\""))
775 else if (fieldType.ToString().Equals(
"long") || fieldType.ToString().Equals(
"\"long\""))
779 else if (fieldType.ToString().Equals(
"string") || fieldType.ToString().Equals(
"\"string\""))
785 throw new ArgumentException(
"Field {fieldName} must be of type bytes, double, float, int, long or string.");
788 IList<string> columnProperties = null;
789 if (null != properties) properties.TryGetValue(fieldName, out columnProperties);
791 if ( ( null != columnProperties ) &&
793 is_column_nullable =
true;
796 Column column =
new Column( fieldName, columnType, columnProperties );
799 column.setIsNullable( is_column_nullable );
801 m_data.columns.Add( column );
803 m_data.columnMap[fieldName] = m_data.columns.Count - 1;
810 private void createSchema()
813 if (m_data.schema != null)
820 if (m_data.schemaString != null)
824 m_data.schema = RecordSchema.Parse(m_data.schemaString);
837 string schema_string =
"";
840 string schema_opening =
"{'type':'record','name':'type_name','fields':[";
842 string schema_closing =
"]}";
844 schema_string += schema_opening;
847 foreach (var column
in m_data.columns)
850 string field_name = (
"'name':'" + column.getName() +
"'");
853 string field_type =
"";
854 if (column.isNullable())
856 field_type = (
"['" + column.getTypeString() +
"','null']");
860 field_type = (
"'" + column.getTypeString() +
"'" );
862 field_type = (
"'type':" + field_type);
865 string field = (
"{" + field_name +
"," + field_type +
"},");
866 schema_string += field;
870 char[] comma = {
',' };
871 schema_string = schema_string.TrimEnd(comma);
873 schema_string += schema_closing;
878 m_data.schema = RecordSchema.Parse(schema_string);
886 m_data.schemaString = m_data.schema.ToString();
const string CHAR1
This property provides optimized memory, disk and query performance for string columns.
ColumnType getType()
Returns the enumeration for the column type.
const string DATETIME
Valid only for 'string' columns.
const string INT16
This property provides optimized memory and query performance for int columns.
const string CHAR128
This property provides optimized memory, disk and query performance for string columns.
bool hasColumn(string name)
KineticaType(string typeSchema)
Create a KineticaType object using the string-formatted schema for the type.
static KineticaType fromObject(Object recordObj, string label="", IDictionary< string, IList< string >> properties=null)
Create a KineticaType object from properties of a record object and Kinetica column properties...
IList< string > type_ids
Type ids of the respective tables in <member name="table_names">.
string type_id
An identifier representing the created type.
KineticaType(string label, IList< Column > columns)
Create a KineticaType object with the given column and label information.
int getColumnIndex(string name)
Column properties used for Kinetica types.
const string TIMESTAMP
Valid only for 'long' columns.
const string CHAR16
This property provides optimized memory, disk and query performance for string columns.
static KineticaType fromTable(Kinetica kinetica, string tableName)
Create a KineticaType object based on an existing table in the database.
static KineticaType fromTypeID(Kinetica kinetica, string typeId)
Create a KineticaType object based on an existing type in the database.
const string CHAR64
This property provides optimized memory, disk and query performance for string columns.
Column getColumn(int index)
const string CHAR4
This property provides optimized memory, disk and query performance for string columns.
const string CHAR2
This property provides optimized memory, disk and query performance for string columns.
string getTypeString()
Returns the string format of the data type.
const string DATE
Valid only for 'string' columns.
const string CHAR8
This property provides optimized memory, disk and query performance for string columns.
const string DECIMAL
Valid only for 'string' columns.
KineticaType(string label, IList< Column > columns, IDictionary< string, IList< string >> properties)
Create a KineticaType object with the given column, label, and property information.
Column(string name, ColumnType type, IList< string > properties=null)
Creates a Column object from the given name, type, and properties.
const string CHAR32
This property provides optimized memory, disk and query performance for string columns.
IList< string > getProperties()
Returns the properties for the column.
IList< Column > getColumns()
const string IPV4
This property provides optimized memory, disk and query performance for string columns representing I...
CreateTypeResponse createType(CreateTypeRequest request_)
Creates a new type describing the layout or schema of a table.
static KineticaType fromClass(Type recordClass, string label, IDictionary< string, IList< string >> properties=null)
Create a KineticaType object from properties of a record class and Kinetica column properties...
ShowTableResponse showTable(ShowTableRequest request_)
Retrieves detailed information about tables, views, and collections.
void saveSourceType(Type sourceType)
Saves the given type as this KineticaType's source type.
void SetKineticaSourceClassToTypeMapping(Type objectType, KineticaType kineticaType)
Saves an object class type to a KineticaType association.
const string CHAR256
This property provides optimized memory, disk and query performance for string columns.
static KineticaType fromClass(Type recordClass, IDictionary< string, IList< string >> properties=null)
Create a KineticaType object from properties of a record class and Kinetica column properties...
KineticaType(string label, string typeSchema, IDictionary< string, IList< string >> properties, string typeID=null)
Create a KineticaType object using the string-formatted schema and properties for its columns...
bool isNullable()
Returns if the column is nullable.
Column getColumn(string name)
static KineticaType fromObject(Object recordObj, IDictionary< string, IList< string >> properties=null)
Create a KineticaType object from properties of a record object and Kinetica column properties...
const string INT8
This property provides optimized memory and query performance for int columns.
string create(Kinetica kinetica)
Given a handle to the server, creates a type in the database based on this data type.
string getName()
Returns the name of the column.
static KineticaType fromDynamicSchema(string dynamic_table_schema_string, Object[] column_headers, Object[] column_types)
Create a KineticaType object based on information provided in a dynamic schema.
override string ToString()
ShowTypesResponse showTypes(ShowTypesRequest request_)
Retrieves information for the specified data type ID or type label.
override string ToString()
KineticaType(IList< Column > columns)
Create a KineticaType object with the given column information.
const string TIME
Valid only for 'string' columns.
const string NULLABLE
This property indicates that this column is nullable.
A set of results returned by Kinetica.createType(string,string,IDictionary<string, IList<string>>,IDictionary<string, string>).
API to talk to Kinetica Database