Required version of Manifold System: 9.0.170.0.
Contents
1. Overview
1.1. .NET / COM languages
1.2. The Root object and third-party applications
1.3. The Context object
1.4. The Application object
1.5. Databases
1.6. Tables, schemas and sequences
1.7. Expressions
1.8. Values
1.9. Geometry
1.10. Tiles
1.11. Language-specific notes
2. Application
2.1. Application.CreateDatabase
2.2. Application.CreateDatabaseForFile
2.3. Application.CreateExpressionParser
2.4. Application.CreateGeomBuilder
2.5. Application.CreatePoint
2.6. Application.CreatePoint3
2.7. Application.CreatePoint4
2.8. Application.CreatePropertySet
2.9. Application.CreatePropertySetParse
2.10. Application.CreateSchema
2.11. Application.CreateTable
2.12. Application.CreateTileBuilder
2.13. Application.CreateTypeConverter
2.14. Application.CreateValueSet
2.15. Application.GetDatabaseRoot
2.16. Application.GetTechnologyForFile
2.17. Application.Log
2.18. Application.MessageBox
2.19. Application.Name
2.20. Application.OpenLog
3. Command
3.1. Command.GetSchema
3.2. Command.Run
4. Context
4.1. Context.Application
5. Curve
5.1. Curve.Type
6. Curve.CoordSet
6.1. Curve.CoordSet indexers
6.2. Curve.CoordSet.Count
7. Curve.Coord3Set
7.1. Curve.Coord3Set indexers
7.2. Curve.Coord3Set.Count
8. Curve.NumberSet
8.1. Curve.NumberSet indexers
8.2. Curve.NumberSet.Count
9. CurveCircle
9.1. CurveCircle.Coord
10. CurveCircle3
10.1. CurveCircle3.Coord3
11. CurveEllipse
11.1. CurveEllipse.Axis
11.2. CurveEllipse.AxisRotation
11.3. CurveEllipse.Center
11.4. CurveEllipse.Coord
12. CurveEllipse3
12.1. CurveEllipse3.Axis
12.2. CurveEllipse3.AxisRotation
12.3. CurveEllipse3.Center3
12.4. CurveEllipse3.Coord3
13. CurveSpline
13.1. CurveSpline.Coords
13.2. CurveSpline.Knots
13.3. CurveSpline.Order
13.4. CurveSpline.Weights
14. CurveSpline3
14.1. CurveSpline3.Coord3s
14.2. CurveSpline3.Knots
14.3. CurveSpline3.Order
14.4. CurveSpline3.Weights
15. Database
15.1. Database.CanDelete
15.2. Database.CanDesign
15.3. Database.CanInsert
15.4. Database.CanMigrate
15.5. Database.CanRefresh
15.6. Database.CanRename
15.7. Database.CanRun
15.8. Database.CanSave
15.9. Database.CanSaveCompact
15.10. Database.Connection
15.11. Database.CreateExpressionParser
15.12. Database.Delete
15.13. Database.Design
15.14. Database.Export
15.15. Database.ExportFile
15.16. Database.GetCache
15.17. Database.GetChild
15.18. Database.GetComponentType
15.19. Database.GetProperties
15.20. Database.GetProperty
15.21. Database.Insert
15.22. Database.IsMigrateNeeded
15.23. Database.IsReadOnly
15.24. Database.IsSaveAsNeeded
15.25. Database.IsSaveCompactNeeded
15.26. Database.IsSaveNeeded
15.27. Database.Migrate
15.28. Database.Refresh
15.29. Database.Rename
15.30. Database.Run
15.31. Database.RunCompile
15.32. Database.Save
15.33. Database.SaveCompact
15.34. Database.Search
15.35. Database.SetProperties
15.36. Database.SetProperty
15.37. Database.Technology
15.38. Database.TechnologyResolved
16. Expression
16.1. Expression.Evaluate
16.2. Expression.GetSource
16.3. Expression.GetTarget
16.4. Expression.Text
17. ExpressionParser
17.1. ExpressionParser.CreateExpression
18. Geom
18.1. Geom.Branches
18.2. Geom.Coords
18.3. Geom.Coord3s
18.4. Geom.Curves
18.5. Geom.GetBytes
18.6. Geom.HasCurves
18.7. Geom.HasZ
18.8. Geom.IsArea
18.9. Geom.IsLine
18.10. Geom.IsPoint
18.11. Geom.Opts
18.12. Geom.Type
19. Geom.Branch
19.1. Geom.Branch.Begin
19.2. Geom.Branch.Coords
19.3. Geom.Branch.Coord3s
19.4. Geom.Branch.Curves
19.5. Geom.Branch.End
20. Geom.BranchSet
20.1. Geom.BranchSet indexers
20.2. Geom.BranchSet.Count
21. Geom.CoordSet
21.1. Geom.CoordSet indexers
21.2. Geom.CoordSet.Count
22. Geom.Coord3Set
22.1. Geom.Coord3Set indexers
22.2. Geom.Coord3Set.Count
23. Geom.CurveSet
23.1. Geom.CurveSet indexers
23.2. Geom.CurveSet.Count
24. GeomBuilder
24.1. GeomBuilder.AddBranch
24.2. GeomBuilder.AddCoord
24.3. GeomBuilder.AddCoord3
24.4. GeomBuilder.AddCurveCircle
24.5. GeomBuilder.AddCurveCircle3
24.6. GeomBuilder.AddCurveEllipse
24.7. GeomBuilder.AddCurveEllipse3
24.8. GeomBuilder.AddCurveSpline
24.9. GeomBuilder.AddCurveSpline3
24.10. GeomBuilder.EndBranch
24.11. GeomBuilder.EndGeom
24.12. GeomBuilder.StartGeom
24.13. GeomBuilder.StartGeomArea
24.14. GeomBuilder.StartGeomArea3
24.15. GeomBuilder.StartGeomLine
24.16. GeomBuilder.StartGeomLine3
24.17. GeomBuilder.StartGeomPoint
24.18. GeomBuilder.StartGeomPoint3
25. GeomWkb
25.1. GeomWkb.GetBytes
26. Point
26.1. Point constructor
26.2. Point.X
26.3. Point.Y
27. Point3
27.1. Point3 constructor
27.2. Point3.X
27.3. Point3.Y
27.4. Point3.Z
28. Point4
28.1. Point4 constructor
28.2. Point4.W
28.3. Point4.X
28.4. Point4.Y
28.5. Point4.Z
29. Property
29.1. Property.Data
29.2. Property.Name
30. PropertySet
30.1. PropertySet indexers
30.2. PropertySet.Clear
30.3. PropertySet.Count
30.4. PropertySet.DeleteProperty
30.5. PropertySet.GetProperty
30.6. PropertySet.SetProperty
30.7. PropertySet.ToJson
31. Root
31.1. Root constructor
31.2. Root.Application
32. Schema
32.1. Schema.AddConstraint
32.2. Schema.AddField
32.3. Schema.AddFieldComputed
32.4. Schema.AddIndex
32.5. Schema.Clear
32.6. Schema.Constraints
32.7. Schema.DeleteConstraint
32.8. Schema.DeleteField
32.9. Schema.DeleteIndex
32.10. Schema.Fields
32.11. Schema.HasItem
32.12. Schema.Indexes
33. Schema.Constraint
33.1. Schema.Constraint.Expression
33.2. Schema.Constraint.ExpressionContext
33.3. Schema.Constraint.Name
34. Schema.ConstraintSet
34.1. Schema.ConstraintSet indexers
34.2. Schema.ConstraintSet.Count
35. Schema.Field
35.1. Schema.Field.Expression
35.2. Schema.Field.ExpressionContext
35.3. Schema.Field.Name
35.4. Schema.Field.Type
35.5. Schema.Field.TypeClr
36. Schema.FieldSet
36.1. Schema.FieldSet indexers
36.2. Schema.FieldSet.Count
37. Schema.Index
37.1. Schema.Index.AddField
37.2. Schema.Index.DeleteField
37.3. Schema.Index.Fields
37.4. Schema.Index.HasField
37.5. Schema.Index.Name
37.6. Schema.Index.Type
38. Schema.IndexField
38.1. Schema.IndexField.Collation
38.2. Schema.IndexField.Descending
38.3. Schema.IndexField.IgnoreAccent
38.4. Schema.IndexField.IgnoreCase
38.5. Schema.IndexField.IgnoreSymbols
38.6. Schema.IndexField.Name
38.7. Schema.IndexField.TileReduce
38.8. Schema.IndexField.TileSize
38.9. Schema.IndexField.TileType
38.10. Schema.IndexField.TileTypeClr
39. Schema.IndexFieldSet
39.1. Schema.IndexFieldSet indexers
39.2. Schema.IndexFieldSet.Count
40. Schema.IndexSet
40.1. Schema.IndexSet indexers
40.2. Schema.IndexSet.Count
41. Sequence
41.1. Sequence.Fetch
41.2. Sequence.GetValues
41.3. Sequence.GetValuesSec
41.4. Sequence.Recompose
42. Table
42.1. Table.CanDelete
42.2. Table.CanDesign
42.3. Table.CanGetVersions
42.4. Table.CanInsert
42.5. Table.CanRename
42.6. Table.CanUpdate
42.7. Table.Delete
42.8. Table.DeleteAll
42.9. Table.DeleteBatch
42.10. Table.Design
42.11. Table.GetSchema
42.12. Table.GetVersionField
42.13. Table.GetVersionScope
42.14. Table.Insert
42.15. Table.InsertBatch
42.16. Table.InsertCaptureKeys
42.17. Table.Rename
42.18. Table.Search
42.19. Table.SearchAll
42.20. Table.SearchBatch
42.21. Table.SearchBatchBTree
42.22. Table.SearchBatchRTree
42.23. Table.SearchBatchRTreeThin
42.24. Table.Update
42.25. Table.UpdateBatch
43. Tile
43.1. Tile.GetBytes
43.2. Tile.Height
43.3. Tile.PixelMissingMasks
43.4. Tile.Pixels
43.5. Tile.Type
43.6. Tile.TypeClr
43.7. Tile.Width
44. Tile.PixelSet
44.1. Tile.PixelSet indexers
45. TileBuilder
45.1. TileBuilder.EndTile
45.2. TileBuilder.Height
45.3. TileBuilder.PixelMissingMasks
45.4. TileBuilder.Pixels
45.5. TileBuilder.StartTile
45.6. TileBuilder.StartTileCopy
45.7. TileBuilder.Type
45.8. TileBuilder.TypeClr
45.9. TileBuilder.Width
46. TileBuilder.PixelSet
46.1. TileBuilder.PixelSet indexers
47. TypeConverter
47.1. TypeConverter.Convert
47.2. TypeConverter.ConvertTilePixels
47.3. TypeConverter.GetTypeClr
47.4. TypeConverter.GetTypeManifold
48. Value
48.1. Value.Data
48.2. Value.Name
48.3. Value.Type
48.4. Value.TypeClr
49. ValueSet
49.1. ValueSet indexers
49.2. ValueSet.AddValue
49.3. ValueSet.AddValueType
49.4. ValueSet.Clear
49.5. ValueSet.Count
49.6. ValueSet.CreateCopy
49.7. ValueSet.CreateLocked
49.8. ValueSet.DeleteValue
49.9. ValueSet.FindValue
49.10. ValueSet.GetValueNames
49.11. ValueSet.HasValue
1. Overview
1.1. .NET / COM languages
The Manifold object model for .NET / COM is designed to work with all .NET languages, including dynamic ones, and with COM languages accessible via active scripting APIs. COM languages use the object model through COM wrappers for .NET objects automatically generated by the system.
The Manifold application includes explicit support for the following languages:
- C# - .NET, installed with .NET by default.
- F# - .NET, requires additional installation.
- IronPython - .NET, requires additional installation.
- IronRuby - .NET, requires additional installation.
- JScript - COM, installed by default.
- JScript.NET - .NET, installed with .NET by default.
- PerlScript - COM, requires additional installation.
- PythonScript - COM, requires additional installation.
- VB.NET - .NET, installed with .NET by default.
- VBScript - COM, installed by default.
Third-party applications may use other .NET or COM languages.
Example code in this document uses C# unless specified otherwise.
The required version of .NET is 4+. .NET 2 / 3 / 3.5 are not supported.
1.2. The Root object and third-party applications
The Root object is used to start and initialize the object model from a third-party application.
A third-party application using the object model for .NET / COM usually includes an instance of EXTNET.DLL which contains the implementation of the Root object. At runtime, the application creates an instance of that object, starting the object model. If the object model starts successfully, the application can access the Root.Application property of the Root object. That returns the Application object used to access the rest of the object model.
The constructor of the Root object takes a string parameter with an optional path to EXT.DLL which contains the implementation of the object model. The application can use that path to choose between multiple installed builds of Manifold on the same system, or to specify the location of the portable install of Manifold if there is no non-portable install. If the path is left empty, the Root object will try to locate EXT.DLL in the default installation path automatically.
1.3. The Context object
The Context object represents the running context of a script. There might be multiple scripts running at the same time, each of these scripts gets its own instance of the Context object.
.NET scripts access the Context object representing their running context via a shared 'Manifold' property of the pre-defined 'Script' class that they declare.
Example .NET script:
// C# class Script { static Manifold.Context Manifold; static void Main() { Manifold.Application.Log("Hello, World!"); Manifold.Application.OpenLog(); } }
COM scripts access the Context object representing their running context via a global variable named 'Manifold'.
Example COM script:
' VBScript Sub Main Manifold.Application.Log "Hello, World!" Manifold.Application.OpenLog End Sub
A running script can access the Context.Application property of the Context object. That returns the Application object used to access the rest of the object model.
1.4. The Application object
The Application object provides access to the rest of the object model.
To access the main database for the object model, use Application.GetDatabaseRoot. To create or open a new database, use Application.CreateDatabase and Application.CreateDatabaseForFile.
The application object allows creating various helper objects like GeomBuilder, TileBuilder or TypeConverter, and provides global services such as Application.Log.
1.5. Databases
The Database object represents a data set.
Databases may contain data source components. To connect to a database for a data source component, use Database.GetChild.
To access tables stored in a database, use Database.Search. The system mfd_root table stores a list of all available components. The system mfd_meta table stores metadata properties for all components. Both mfd_root and mfd_meta tables are guaranteed to exist in any database, regardless of what particular data set it represents.
To create a new component, use Database.Insert. The name of a new component must be unique. Component names are case-insensitive. The database may alter the requested name of the component when inserting it. For example, a database representing a connection to SQL Server may alter the requested name for a new table to include the prefix of the current database schema.
To change the schema of an existing table component, use Table.Design.
To rename an existing component, use Database.Rename.
To delete an existing component, use Database.Delete.
To read component properties, use Database.GetProperty or Database.GetProperties. To write component properties, use Database.SetProperty or Database.SetProperties.
To run a query in the context of a database, use Database.Run. All databases support running queries using the Manifold query engine. Some databases, such as databases representing connections to SQL Server or PostgreSQL, also support running queries using the native query engine specific to the database. In the latter databases, Database.Run first inspects the text of the query and looks for the '-- $manifold$' directive. If the text includes the directive, the database runs the query using the Manifold query engine, otherwise it runs the query using the native query engine specific to the database.
To compile a query in order to run it later, use Database.RunCompile.
Databases for some technologies, most notably MAP files, may not save data to persistent storage until explicitly requested to do so. To find out if such a database contains unsaved changes, use Database.IsSaveNeeded. To save changes, use Database.Save.
Database objects are expensive. It is best to dispose of them immediately after they are no longer needed.
1.6. Tables, schemas and sequences
The Table object represents a table.
The definition of a table is represented by a Schema object. To get the schema of a table, use Table.GetSchema.
A schema contains the list of fields, the list of indexes and the list of constraints. Each schema item has a unique name. For example, the name of an index cannot coincide with the name of a field or a constraint. Names of schema items are case-insensitive.
A field has a name and a type. A computed field also has an expression used to compute field values. Attempting to insert a record or change record field values updates the values of computed fields automatically. Field expressions use SQL syntax.
An index has a name, a type and a list of fields. An index always uses at least one field. The order of fields in the index determines the behavior of the index. Index fields have options that specify how the index handles field values.
A constraint has a name and a boolean expression. Attempting to insert a record or change record field values evaluates constraint expressions. If any of the constraint expressions evaluate to false or fail to evaluate due to an error, the operation is rejected. Constraint expressions use SQL syntax.
To change the schema of a table, use Table.Design.
To rename an item in the schema of a table, use Table.Rename.
Tables return record field values via Sequence objects.
Initially, a sequence is empty. To fetch data for the next record into a sequence, use Sequence.Fetch. To access data for the current record in a sequence, use Sequence.GetValues. When the sequence has no more data to return, Sequence.Fetch will return false.
To fetch field values for all records in a table, use Table.SearchAll. To search a table using an index, use Table.SearchBatch and provide the key values to search with. Table.SearchBatchBTree and Table.SearchBatchRTree allow specifying additional search options. To search a table for a single record using an unique index, use Table.Search and provide the key values for the record.
To insert a new record into a table, use Table.Insert. To insert a new record and capture the values for automatically generated fields, use Table.InsertCaptureKeys. To insert multiple records, use Table.InsertBatch.
To delete an existing record, use Table.Delete. To delete multiple records, use Table.DeleteBatch. Deleting records requires having an unique index. Records to delete are specified via the values of the key fields in that index.
To change field values in an existing record, use Table.Update. To change field values in multiple records, use Table.UpdateBatch. Updating records requires having an unique index. Records to update are specified via the values of the key fields in that index.
Many tables track changes made to data via version numbers. Version numbers are opaque values and are only intended to be compared for equality. To get the current version number for a table field, use Table.GetVersionField. To get the current version number for all table records or for a different scope other than a field, use Table.GetVersionScope.
Table and sequence objects are expensive. It is best to dispose of them immediately after they are no longer needed.
1.7. Expressions
In addition to running queries via Database.Run or Database.RunCompile, scripts can prepare and run fragments of SQL code using Expression objects.
To create an expression, first create an ExpressionParser object using either Application.CreateExpressionParser or Database.CreateExpressionParser. Then create an Expression object using ExpressionParser.CreateExpression. If the expression uses parameters, specify their names and types in the call.
To evaluate an expression, use Expression.Evaluate. If the expression uses parameters, specify their values in the call. The same expression object can be used from multiple threads simultaneously.
Expression and expression parser objects are expensive. It is best to dispose of them immediately after they are no longer needed.
1.8. Values
Record values and parameters for queries and expressions are passed via ValueSet objects.
A value set is a collection of values with unique names. Value names are case-insensitive.
To locate a specific value in a value set, use ValueSet indexers. To access data associated with the value, use Value.Data.
To add a new value to a value set, use ValueSet.AddValue. To delete a value from a value set, use ValueSet.DeleteValue.
Many database and table operations contain optimizations for repeated use of the same value set. To use these optimizations, compose a value set with the names of desired values, then create a locked value set with these values using ValueSet.CreateLocked and perform the desired operation with different values passing data through the locked value set. A locked value set disallows adding or deleting values but allows altering data associated with the values.
Data values are represented using the following types:
-
FLOAT32 - System.Single (C#: float)
-
FLOAT64 - System.Double (C#: double)
-
INT8 - System.SByte (C#: sbyte)
-
UINT8 - System.Byte (C#: byte)
-
INT16 - System.Int16 (C#: short)
-
UINT16 - System.UInt16 (C#: ushort)
-
INT32 - System.Int32 (C#: int)
-
UINT32 - System.UInt32 (C#: uint)
-
INT64 - System.Int64 (C#: long)
-
UINT64 - System.UInt64 (C#: ulong)
-
FLOAT32X2 and other X2 types - Point<T>
-
FLOAT32X3 and other X3 types - Point3<T>
-
FLOAT32X4 and other X4 types - Point4<T>
-
VARBINARY - System.Array of System.Byte (C#: byte[])
-
VARCHAR - System.String (C#: string)
-
NVARCHAR - System.String (C#: string)
-
BOOLEAN - System.Boolean (C#: bool)
-
DATETIME - System.DateTime
-
UUID - System.Guid
-
GEOM - Geom
-
GEOMMFD - Geom
-
GEOMWKB - GeomWkb
-
TILE - Tile
To convert a value to a different type, use TypeConverter.Convert.
1.9. Geometry
Geometry values are represented using Geom objects.
A geometry value is either a point, a line or an area. A geometry value is either 2d or 3d. To determine the type of a geometry value, use Geom.Type or Geom.IsArea, Geom.IsLine, Geom.IsPoint. To determine if a geometry value is 2d or 3d, use Geom.HasZ.
The coordinates in a geometry value are split into branches. A geometry value has at least one branch, and can have multiple branches. Branches contain coordinates. The coordinates of a 2d geometry value are Point objects. The coordinates of a 3d geometry value are Point3 objects. To access branches of a geometry value, use Geom.Branches. To access coordinates of a geometry value, use Geom.Coords or Geom.Coord3s. To access coordinates of a specific branch, use Geom.Branch.Coords or Geom.Branch.Coord3s.
Branches of line or area geometry values can have curve segments. The parameters of a curve depend on the curve type. Curves of different types are represented via CurveCircle, CurveCircle3, CurveEllipse, CurveEllipse3, CurveSpline and CurveSpline3 objects. To access curves of a geometry value, use Geom.Curves. To access curves of a specific branch, use Geom.Branch.Curves.
To compose a new geometry value, use the GeomBuilder object.
First, start a new geometry value using GeomBuilder.StartGeomArea, GeomBuilder.StartGeomLine or a similar method. Then add a new branch using GeomBuilder.AddBranch. Add one or more coordinates using GeomBuilder.AddCoord or GeomBuilder.AddCoord3. Add curves using GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3. After the branch is complete, finish it using GeomBuilder.EndBranch. Add more branches if desired. After all branches are added, finish composing the geometry value using GeomBuilder.EndGeom.
The same geometry builder object can be used to compose multiple geometry values.
1.10. Tiles
Tile values are represented using Tile objects.
A tile value is a rectangular grid of pixels. To determine the dimensions of a tile value, use Tile.Width and Tile.Height.
To access pixel values, use Tile.Pixels. In strongly-typed languages such as C#, the returned object has to be cast to a Tile.PixelSet object with the type corresponding to the type of pixel values. To access the value of a particular pixel, use Tile.PixelSet indexers.
Tile pixels can be marked as missing (invisible). To access missing masks for pixel values, use Tile.PixelMissingMasks. To access the missing mask of a particular pixel, use Tile.PixelSet indexers. If the missing mask of a pixel is true, the pixel is missing (invisible).
To compose a new tile value, use the TileBuilder object.
First, start a new tile value using TileBuilder.StartTile or TileBuilder.StartTileCopy. Then alter pixel values and missing masks using TileBuilder.Pixels and TileBuilder.PixelMissingMasks. After all pixel values and missing masks are set, finish composing the tile value using TileBuilder.EndTile.
The same tile builder object can be used to compose multiple tile values.
1.11. Language-specific notes
The object model makes full use of .NET features related to performance, such as generics. These features are unavailable for COM languages such as VBScript. In order to use parts of the object model that use these features from COM languages, the object model exposes additional properties and methods.
The following collection objects expose the EnumObj property that can be used with 'for each'-like constructs in COM languages:
Example:
' VBScript Sub Main Set app = Manifold.Application Set values = app.CreateValueSet() values.AddValue "a" values.AddValue "b" For Each value In values.EnumObj ' have to use EnumObj app.Log value.Name Next app.OpenLog End Sub ' result: a ' ....... b
Iterating over a collection using explicit indexes does not require using the EnumObj property.
Example:
' VBScript Sub Main Set app = Manifold.Application Set values = app.CreateValueSet() values.AddValue "a" values.AddValue "b" For index = 0 To values.Count - 1 app.Log values(index).Name Next app.OpenLog End Sub ' result: a ' ....... b
The following properties and methods expose additional variants that allow working with values of Point<T>, Point3<T> and Point4<T> generic types:
-
Application.CreatePoint (Application.CreatePointObj)
-
Application.CreatePoint3 (Application.CreatePoint3Obj)
-
Application.CreatePoint4 (Application.CreatePoint4Obj)
-
CurveCircle.Coord (CurveCircle.CoordObj)
-
CurveCircle3.Coord3 (CurveCircle3.Coord3Obj)
-
CurveEllipse.Center (CurveEllipse.CenterObj)
-
CurveEllipse.Coord (CurveEllipse.CoordObj)
-
CurveEllipse3.Center3 (CurveEllipse3.Center3Obj)
-
CurveEllipse3.Coord3 (CurveEllipse3.Coord3Obj)
-
CurveSpline.Coords (CurveSpline.CoordObjs)
-
CurveSpline3.Coord3s (CurveSpline3.Coord3Objs)
-
Geom.Coords (Geom.CoordObjs)
-
Geom.Coord3s (Geom.Coord3Objs)
-
Geom.Branch.Coords (Geom.Branch.CoordObjs)
-
Geom.Branch.Coord3s (Geom.Branch.Coord3Objs)
-
Tile.Pixels (Tile.PixelObjs)
-
TileBuilder.Pixels (TileBuilder.PixelObjs)
-
TypeConverter.Convert (TypeConverter.ConvertObj)
-
Value.Data (Value.DataObj)
-
ValueSet.AddValue (ValueSet.AddValueObj)
Example:
' VBScript Sub Main Set app = Manifold.Application Set values = app.CreateValueSet() values.AddValueObj "a", app.CreatePointObj(2, 3) ' have to use CreatePointObj Set point = values("a").DataObj ' have to use DataObj app.Log point.X & " : " & point.Y app.OpenLog End Sub ' result: 2 : 3
Disposing of expensive objects in COM languages is done by calling the Dispose method.
Example:
' VBScript Sub Main Set app = Manifold.Application Set db = app.GetDatabaseRoot() app.Log db.GetProperty("mfd_root", "Folder") db.Dispose ' disposing of database app.OpenLog End Sub ' result: System Data
2. Application
2.1. Application.CreateDatabase
Syntax
Database CreateDatabase() Database CreateDatabase(string technology, string connection, bool forceDiscover)
Parameters
technology - technology name, eg, "manifold". Case-insensitive.
connection - connection string.
forceDiscover - if true, forces the database to completely finish discovery of all available components before the method returns; if false, the database will discover available components progressively in a background thread after the method returns.
Return Value
Returns a new temporary database or a new database for the specified technology and connection string.
Notes
The method creates a database for the specified technology and connection string. If the method is called without parameters, it creates a new temporary MAP file.
If forceDiscover is true, Database.Search is guaranteed to return data for any of the available components, and the mfd_root table lists all available components as well.
If forceDiscover is false, the method finishes faster with the discovery process offloaded to a background thread, but Database.Search may fail to return data for some of the available components until they are discovered, and mfd_root may not list some of the available components until they are discovered either.
The forceDiscover parameter should normally be set to true, unless the caller wants to reduce the time it takes to connect to the database and is prepared to deal with the components being discovered progressively in a background thread (for example, waiting until the discovery completes in case the requested component is not yet available).
To create a database for a file, determining the technology automatically, use Application.CreateDatabaseForFile. To determine the technology for a file, use Application.GetTechnologyForFile.
Database objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { using (Manifold.Table meta = db.Search("mfd_meta")) { Manifold.Schema metaSchema = meta.GetSchema(); app.Log(metaSchema.Fields.Count.ToString()); } } app.OpenLog(); } // result: 4
The above example creates a new temporary MAP file, finds the mfd_meta table and reports the number of fields in the table.
// tries to read file: c:\data\example.img static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\example.img"); string conn = connProperties.ToJson(); string tech = "imgerdas"; using (Manifold.Database db = app.CreateDatabase(tech, conn, true)) { Manifold.Table tiles = db.Search("example tiles"); app.Log("Accessed image data"); } app.OpenLog(); } // result: Accessed image data
The above example connects to an ERDAS IMG file and retrieves a table that contains image data. The connection string is composed with the help of the PropertySet object.
2.2. Application.CreateDatabaseForFile
Syntax
Database CreateDatabaseForFile(string path, bool forceDiscover)
Parameters
path - path to file, eg, "c:\data.csv".
forceDiscover - if true, forces the database to completely finish discovery of all available components before the method returns; if false, the database will discover available components progressively in a background thread after the method returns.
Return Value
Returns a new database for the specified file.
Notes
The method attempts to automatically determine the connection technology from the specified path. The method first analyzes the filename. If the filename matches more than one technology (for example, the file named "A.NTF" could be an NTF file or a NITF file), the method attempts to determine the technology from the file contents.
If forceDiscover is true, Database.Search is guaranteed to return data for any of the available components, and the mfd_root table lists all available components as well.
If forceDiscover is false, the method finishes faster with the discovery process offloaded to a background thread, but Database.Search may fail to return data for some of the available components until they are discovered, and mfd_root may not list some of the available components until they are discovered either.
To create a database with a specific technology and connection string, use Application.CreateDatabase. To determine the technology for a file, use Application.GetTechnologyForFile.
Database objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// tries to read file: c:\data\example.img static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabaseForFile(@"c:\data\example.img", true)) { Manifold.Table tiles = db.Search("example tiles"); app.Log("Accessed image data"); } app.OpenLog(); } // result: Accessed image data
The above example connects to an IMG file and retrieves a table that contains image data. The file format can be ERDAS IMG, ENVI IMG, IDRISI IMG or any other supported technology that matches the filename.
2.3. Application.CreateExpressionParser
Syntax
ExpressionParser CreateExpressionParser()
Return Value
Returns a new expression parser used to create expressions.
Notes
Expressions created by the expression parser returned by this method cannot reference components stored in databases by name. They can, however, access data in arbitrary tables by taking tables as parameters.
A single expression parser can be used to create any number of expressions. There is no need to create a new expression parser for each new expression.
Expression parser objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.ExpressionParser parser = app.CreateExpressionParser()) { using (Manifold.Expression expression = parser.CreateExpression("1+2")) { Manifold.ValueSet result = expression.Evaluate(); app.Log(result[0].Data.ToString()); } } app.OpenLog(); } // result: 3
The above example creates a new expression parser and a new expression without parameters, then evalutes the expression and reports the result.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.ExpressionParser parser = app.CreateExpressionParser()) { Manifold.ValueSet source = app.CreateValueSet(); source.AddValueType("a", typeof(int)); source.AddValueType("b", typeof(int)); using (Manifold.Expression expression = parser.CreateExpression("a+b", source)) { source[0].Data = 1; source[1].Data = 2; Manifold.ValueSet result = expression.Evaluate(source); app.Log(result[0].Data.ToString()); } } app.OpenLog(); } // result: 3
The above example creates a new expression parser and a new expression with two parameters, then evaluates the expression passing parameter values and reports the result.
2.4. Application.CreateGeomBuilder
Syntax
GeomBuilder CreateGeomBuilder()
Return Value
Returns a new geom builder used to create geometry values.
Notes
A single geom builder can be used to create any number of geometry values. There is no need to create a new geom builder for each new geometry value.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Geom geom; { Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomPoint(); // allows multipoint builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(3, 4)); builder.AddCoord(new Manifold.Point<double>(5, 6)); builder.EndBranch(); geom = builder.EndGeom(); } app.Log(geom.Coords.Count.ToString()); app.OpenLog(); } // result: 2
The above example builds a new geometry value and reports the number of coordinates in that value.
2.5. Application.CreatePoint
Syntax
Point<T> CreatePoint(T x, T y)
COM languages:
Point<double> CreatePointObj(double x, double y)
Parameters
x - 1st coordinate.
y - 2nd coordinate.
Return Value
Returns a new point with the specified coordinates.
Notes
Point objects can also be created directly using 'new'. See Point constructor.
To access the coordinates of an existing object, use Point.X and Point.Y.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Point<int> p = app.CreatePoint<int>(1, 2); app.Log(p.ToString()); app.OpenLog(); } // result: [ 1, 2 ]
The above example creates a new point with the specified coordinates.
2.6. Application.CreatePoint3
Syntax
Point3<T> CreatePoint3(T x, T y, T z)
COM languages:
Point3<double> CreatePoint3Obj(double x, double y, double z)
Parameters
x - 1st coordinate.
y - 2nd coordinate.
z - 3rd coordinate.
Return Value
Returns a new point with the specified coordinates.
Notes
Point objects can also be created directly using 'new'. See Point3 constructor.
To access the coordinates of an existing object, use Point3.X, Point3.Y and Point3.Z.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Point3<int> p = app.CreatePoint3<int>(1, 2, 3); app.Log(p.ToString()); app.OpenLog(); } // result: [ 1, 2, 3 ]
The above example creates a new point with the specified coordinates.
2.7. Application.CreatePoint4
Syntax
Point4<T> CreatePoint4(T x, T y, T z, T w)
COM languages:
Point4<double> CreatePoint4Obj(double x, double y, double z, double w)
Parameters
x - 1st coordinate.
y - 2nd coordinate.
z - 3rd coordinate.
w - 4th coordinate.
Return Value
Returns a new point with the specified coordinates.
Notes
Point objects can also be created directly using 'new'. See Point4 constructor.
To access the coordinates of an existing object, use Point4.X, Point4.Y, Point4.Z and Point4.W.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Point4<int> p = app.CreatePoint4<int>(1, 2, 3, 4); app.Log(p.ToString()); app.OpenLog(); } // result: [ 1, 2, 3, 4 ]
The above example creates a new point with the specified coordinates.
2.8. Application.CreatePropertySet
Syntax
PropertySet CreatePropertySet()
Return Value
Returns a new empty property set.
Notes
Property sets are used to store component properties, to parse and prepare connection strings and for other purposes.
To create a property set from a JSON string, use Application.CreatePropertySetParse. To print properties to a JSON string, use PropertySet.ToJson.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet properties = app.CreatePropertySet(); app.Log(properties.ToJson()); app.OpenLog(); } // result: { }
The above example creates a new property set and prints it to a JSON string.
2.9. Application.CreatePropertySetParse
Syntax
PropertySet CreatePropertySetParse(string value) PropertySet CreatePropertySetParse(string packed, bool strict)
Parameters
value - string value to parse.
strict - if true, only JSON format is accepted, otherwise a name=value format is accepted as well.
Return Value
Returns a new property set with properties parsed from a string.
Notes
The method parses the specified string value into a set of properties.
If the strict parameter is true, the only supported format is JSON.
If the strict parameter is false, in addition to JSON, the method also supports the name=value format with pairs of values separated by a semicolon. This format has been used by older builds of Manifold System and is used with various extensions by many databases.
Property sets are used to store component properties, to parse and prepare connection strings and for other purposes.
To create a new blank property set, use Application.CreatePropertySet. To print properties to a JSON string, use PropertySet.ToJson.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; string json = "{ \"x\": 1, \"y\": 2 }"; // quotes inside JSON are escaped Manifold.PropertySet properties = app.CreatePropertySetParse(json); app.Log(properties.GetProperty("x")); app.OpenLog(); } // result: 1
The above example creates a new property set from a JSON string and prints the value of a property.
2.10. Application.CreateSchema
Syntax
Schema CreateSchema()
Return Value
Returns a new empty schema used to describe tables.
Notes
To add a new table with the specified schema, use Database.Insert. To get the schema of an existing table, use Table.GetSchema.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { Manifold.Schema schema = db.Search("mfd_root").GetSchema(); string inserted = db.Insert("root_structure", "table", schema); app.Log("Copy of mfd_root with no records: " + inserted); } app.OpenLog(); } // result: Copy of mfd_root with no records: root_structure
The above example creates a new table with the same schema as the system mfd_root table.
2.11. Application.CreateTable
Syntax
Table CreateTable()
Return Value
Returns a new temporary table.
Notes
The returned table contains default fields and indexes. The table schema can be altered using Table.Design. The table supports indexes, but not computed fields or constraints. To create a temporary table that supports computed fields and constraints, create a temporary database using Application.CreateDatabase and create a table on that database.
Temporary tables are used to temporarily store data in a structured format.
Table objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { Manifold.Schema schema = table.GetSchema(); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(field.Name); } app.OpenLog(); } // result: mfd_id
The above example creates a new temporary table and lists fields in the table.
2.12. Application.CreateTileBuilder
Syntax
TileBuilder CreateTileBuilder()
Return Value
Returns a new tile builder used to create tile values.
Notes
A single tile builder can be used to create any number of tile values. There is no need to create a new tile builder for each new tile value.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Tile tile; { Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(2, 2, "uint8"); Manifold.TileBuilder.PixelSet<byte> builderPixels = (Manifold.TileBuilder.PixelSet<byte>)builder.Pixels; builderPixels[0, 0] = 5; builderPixels[0, 1] = 6; builderPixels[1, 0] = 7; builderPixels[1, 1] = 8; tile = builder.EndTile(); } Manifold.Tile.PixelSet<byte> pixels = (Manifold.Tile.PixelSet<byte>)tile.Pixels; app.Log(pixels[1, 1].ToString()); app.OpenLog(); } // result: 8
The above example builds a new tile value and reports the value of a pixel in the tile.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Tile tile; { Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(3, 1, "uint8x3"); Manifold.TileBuilder.PixelSet<Manifold.Point3<byte>> builderPixels = (Manifold.TileBuilder.PixelSet<Manifold.Point3<byte>>)builder.Pixels; builderPixels[0, 0] = new Manifold.Point3<byte>(1, 2, 3); builderPixels[1, 0] = new Manifold.Point3<byte>(4, 5, 6); builderPixels[2, 0] = new Manifold.Point3<byte>(7, 8, 9); tile = builder.EndTile(); } Manifold.Tile.PixelSet<Manifold.Point3<byte>> pixels = (Manifold.Tile.PixelSet<Manifold.Point3<byte>>)tile.Pixels; app.Log(pixels[2, 0].ToString()); app.OpenLog(); } // result: [ 7, 8, 9 ]
The above example builds a new tile value with multiple channels and reports the value of a pixel in the tile.
2.13. Application.CreateTypeConverter
Syntax
TypeConverter CreateTypeConverter()
Return Value
Returns a type converter used to convert values between Manifold types.
Notes
A single type converter can be used to convert any number of values.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) app.Log(converter.Convert(new Manifold.Point<int>(2, 3), "int32x3").ToString()); app.OpenLog(); } // result: [ 2, 3, 0 ]
The above example creates a new type converter and uses it to convert a point with two coordinates into a point with three coordinates.
2.14. Application.CreateValueSet
Syntax
ValueSet CreateValueSet()
Return Value
Returns a new empty value set used to pass values to and from tables, queries and expressions.
Notes
To create a copy of an existing value set, use ValueSet.CreateCopy.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); app.Log(values.Count.ToString()); app.OpenLog(); } // result: 0
The above example creates a new value set and reports the number of values.
2.15. Application.GetDatabaseRoot
Syntax
Database GetDatabaseRoot()
Return Value
Returns the main database for the object model.
Notes
If the method is called in the context of the Manifold application, it returns the currently opened MAP file.
Database objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) { string[] fields = new string[] { "Name" }; using (Manifold.Sequence sequence = table.SearchAll(fields)) { while (sequence.Fetch()) app.Log(sequence.GetValues()[0].Data.ToString()); } } } app.OpenLog(); } // result: mfd_root // ......: mfd_meta // ......: Script
The above example lists all components in the currently opened MAP file in the Manifold application.
2.16. Application.GetTechnologyForFile
Syntax
string GetTechnologyForFile(string path, bool mayOpen)
Parameters
path - path to file, eg, "c:\data.csv".
mayOpen - if true, the application may scan file contents to resolve ambiguities, otherwise the application may not scan file contents.
Return Value
Returns best guess for the technology likely used by file.
Notes
The method attempts to automatically determine the technology from the specified path. The method first analyzes the filename. If the filename matches more than one technology (for example, the file named "A.NTF" could be an NTF file or a NITF file) and mayOpen is true, the method attempts to determine the technology from the file contents. If the filename matches more than one technology and mayOpen is false, the method returns one of the matching technologies.
To create a database for a file, determining the technology automatically, use Application.CreateDatabaseForFile. To create a database with a specific technology and connection string, use Application.CreateDatabase.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; app.Log(app.GetTechnologyForFile(@"c:\data\country.shp", false)); app.OpenLog(); } // result: shp
The above example determines the technology for a SHP file. The SHP file does not have to exist.
2.17. Application.Log
Syntax
void Log(string text)
Parameters
text - text message.
Notes
The method appends the specified text message to the log.
If the text message is empty, the call is ignored.
Leading whitespace is preserved. Trailing whitespace is trimmed. Multiline text messages are split into different log lines.
Log lines generated by a script appear with the '++' type prefix.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; app.Log(""); // ignored app.Log(" leading whitespace"); app.Log("trailing whitespace \r\n"); app.Log("multiple\r\nlines"); app.OpenLog(); } // result: leading whitespace // ....... trailing whitespace // ....... multiple // ....... lines
The above example illustrates the handling of whitespace and line breaks.
2.18. Application.MessageBox
Syntax
void MessageBox(string text, string caption)
Parameters
text - text message.
caption - caption.
Notes
The method displays a message box with the specified text and caption.
If caption is an empty string, the method will use the default caption.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; app.MessageBox("Message text", "Caption"); }
The above example displays a message box with custom text and caption.
2.19. Application.Name
Syntax
string Name
Return Value
Returns the name of the object model application, such as "Manifold System".
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; app.Log(app.Name); app.OpenLog(); } // result: Manifold System
The above example appends the name of the object model application to the log.
2.20. Application.OpenLog
Syntax
void OpenLog()
Notes
If the method is called in the context of the Manifold application, it opens the log window. Otherwise, the method does nothing.
3. Command
3.1. Command.GetSchema
Syntax
Schema GetSchema()
Return Value
Returns the schema of the result table of the compiled query.
Notes
The returned schema lists fields, indexes and constraints in the result table. A table always has at least one field.
To run a compiled query and obtain the result table, use Command.Run.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT name, type FROM [mfd_root]"; using (Manifold.Command command = db.RunCompile(text)) { Manifold.Schema schema = command.GetSchema(); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(field.Name); } } app.OpenLog(); } // result: Name // ....... Type
The above example creates a new compiled query and reports fields in its result table.
3.2. Command.Run
Syntax
Table Run() Table Run(ValueSet values)
Parameters
values - parameter values.
Return Value
Returns the result table of the compiled query.
Notes
The method attempts to run the compiled query.
The values parameter contains optional parameter values for the query. If the query uses no parameters, the passed values are ignored. If the query uses parameters and one or more of the parameters is not passed, the method will fail.
For action queries, the returned table contains a single value representing the number of affected records.
Compiled queries are usually used to run the same query multiple times with different parameter values. Running a compiled query multiple times performs faster than running the same query multiple times using Database.Run.
All databases support running compiled queries using the Manifold query engine. Some databases, such as databases representing connections to SQL Server or PostgreSQL, also support running compiled queries using the native query engine specific to the database. In the latter databases, the compiled query is set to use either the Manifold query engine or the native query engine specific to the database based on the text of the query by Database.RunCompile.
When running a compiled query with parameters multiple times, consider passing parameter values using a locked value set to improve performance. To create a locked value set, use ValueSet.CreateLocked.
Table objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT name, type FROM [mfd_root]"; using (Manifold.Command command = db.RunCompile(text)) { using (Manifold.Table table = command.Run()) { using (Manifold.Sequence sequence = table.SearchAll(new string[] { "name", "type" })) { if (sequence != null) { while (sequence.Fetch()) { Manifold.ValueSet values = sequence.GetValues(); app.Log(string.Format("{0} : {1}", values[0].Data, values[1].Data)); } } } } } } app.OpenLog(); } // result: mfd_root : table // ....... mfd_meta : table // ....... Script : script
The above example creates a new compiled query that lists components in the root database, runs it and reports the results.
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT name FROM [mfd_root] WHERE type = StringToLowerCase(@t)"; Manifold.ValueSet parameters = app.CreateValueSet(); parameters.AddValueType("t", "nvarchar"); using (Manifold.Command command = db.RunCompile(text, parameters)) { string[] types = new string[] { "table", "script", "drawing" }; for (int index = 0; index < types.Length; ++index) { app.Log("Listing components of type: " + types[index]); // set parameter value parameters[0].Data = types[index]; // run command and list results using (Manifold.Table table = command.Run(parameters)) { using (Manifold.Sequence sequence = table.SearchAll(new string[] { "name" })) { if (sequence != null) { while (sequence.Fetch()) app.Log(" " + sequence.GetValues()[0].Data.ToString()); } } } } } } app.OpenLog(); } // result: Listing components of type: table // ....... mfd_root // ....... mfd_meta // ....... Listing components of type: script // ....... Script // ....... Listing components of type: drawing
The above example creates a new compiled query that lists components of the specified type in the root database, runs it with several different component types and reports the results.
4. Context
4.1. Context.Application
Syntax
Application Application
Return Value
Returns the application object.
5. Curve
5.1. Curve.Type
Syntax
string Type
Return Value
Returns the type of the curve.
Notes
If the type of the curve is an empty string, the curve is a straight line segment.
To access curve parameters, convert the curve object to the appropriate subtype.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveCircle(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); Manifold.Geom.CurveSet curves = geom.Curves; for (int index = 0; index < curves.Count; ++index) app.Log(string.Format("{0} : {1}", index, curves[index].Type)); app.OpenLog(); } // result: 0 : circle // ....... 1 :
The above example composes a geom value with a single circular arc and reports the type of each curve. The last curve of each branch is ignored in computations and is set to a straight line segment.
6. Curve.CoordSet
6.1. Curve.CoordSet indexers
Syntax
Point<double> object[int index]
Parameters
index - index of coordinate.
Return Value
Returns the coordinate with the specified index.
6.2. Curve.CoordSet.Count
Syntax
int Count
Return Value
Returns the number of coordinates.
7. Curve.Coord3Set
7.1. Curve.Coord3Set indexers
Syntax
Point3<double> object[int index]
Parameters
index - index of coordinate.
Return Value
Returns the coordinate with the specified index.
7.2. Curve.Coord3Set.Count
Syntax
int Count
Return Value
Returns the number of coordinates.
8. Curve.NumberSet
8.1. Curve.NumberSet indexers
Syntax
double object[int index]
Parameters
index - index of numeric value.
Return Value
Returns the value with the specified index.
8.2. Curve.NumberSet.Count
Syntax
int Count
Return Value
Returns the number of values.
9. CurveCircle
9.1. CurveCircle.Coord
Syntax
Point<double> Coord
COM languages:
Point<double> CoordObj
Return Value
Returns the coordinate on the circular arc.
10. CurveCircle3
10.1. CurveCircle3.Coord3
Syntax
Point3<double> Coord3
COM languages:
Point3<double> Coord3Obj
Return Value
Returns the coordinate on the 3d circular arc.
11. CurveEllipse
11.1. CurveEllipse.Axis
Syntax
double Axis
Return Value
Returns the major axis of the ellipse.
11.2. CurveEllipse.AxisRotation
Syntax
double Axis
Return Value
Returns the rotation angle of the major axis of the ellipse in radians.
11.3. CurveEllipse.Center
Syntax
Point<double> Center
COM languages:
Point<double> CenterObj
Return Value
Returns the center of the ellipse.
11.4. CurveEllipse.Coord
Syntax
Point<double> Coord
COM languages:
Point<double> CoordObj
Return Value
Returns the coordinate on the ellipsoidal arc.
12. CurveEllipse3
12.1. CurveEllipse3.Axis
Syntax
double Axis
Return Value
Returns the major axis of the 3d ellipse.
12.2. CurveEllipse3.AxisRotation
Syntax
double Axis
Return Value
Returns the rotation angle of the major axis of the 3d ellipse on the ellipse plane in radians.
12.3. CurveEllipse3.Center3
Syntax
Point3<double> Center3
COM languages:
Point3<double> Center3Obj
Return Value
Returns the center of the 3d ellipse.
12.4. CurveEllipse3.Coord3
Syntax
Point3<double> Coord3
COM languages:
Point3<double> Coord3Obj
Return Value
Returns the coordinate on the 3d ellipsoidal arc.
13. CurveSpline
13.1. CurveSpline.Coords
Syntax
Curve.CoordSet Coords
COM languages:
Curve.CoordSet CoordObjs
Return Value
Returns intermediate control points of the spline.
13.2. CurveSpline.Knots
Syntax
Curve.NumberSet Knots
Return Value
Returns knots used for the spline.
13.3. CurveSpline.Order
Syntax
int Order
Return Value
Returns the order of the spline.
13.4. CurveSpline.Weights
Syntax
Curve.NumberSet Weights
Return Value
Returns weights for the starting coordinate, each of the intermediate control points and the ending coordinate of the spline.
14. CurveSpline3
14.1. CurveSpline3.Coord3s
Syntax
Curve.Coord3Set Coord3s
COM languages:
Curve.Coord3Set Coord3Objs
Return Value
Returns intermediate control points of the 3d spline.
14.2. CurveSpline3.Knots
Syntax
Curve.NumberSet Knots
Return Value
Returns knots used for the 3d spline.
14.3. CurveSpline3.Order
Syntax
int Order
Return Value
Returns the order of the 3d spline.
14.4. CurveSpline3.Weights
Syntax
Curve.NumberSet Weights
Return Value
Returns weights for the starting coordinate, each of the intermediate control points and the ending coordinate of the 3d spline.
15. Database
15.1. Database.CanDelete
Syntax
bool CanDelete
Return Value
Returns true if the database supports deleting components, otherwise returns false.
Notes
Databases for some technologies do not support deleting components at all. Databases for other technologies may disable deleting components, for example, if they are opened in read-only mode.
To delete a component, use Database.Delete.
Attempting to delete a particular component may fail even if the database reports that it supports deleting components in general. For example, attempting to delete a particular component on a SQL Server database might fail due to insufficient permissions, whereas attempting to delete a different component in the same database would succeed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { // insert new component if (!db.CanInsert) { app.Log("Can't insert new components"); return; } string inserted = db.Insert("new component", "comments"); app.Log("Inserted component: " + inserted); // delete inserted component if (!db.CanDelete) { app.Log("Can't delete existing components"); return; } db.Delete(inserted); app.Log("Deleted component: " + inserted); } app.OpenLog(); } // result: Inserted component: new component // ....... Deleted component: new component
The above example inserts a new comments component and then deletes it.
The example assumes the root database is opened in read-write mode.
The example saves the name under which the component has been inserted, because that name might be different from the name specified in the call to Database.Insert.
15.2. Database.CanDesign
Syntax
bool CanDesign
Return Value
Returns true if database tables support changing table schemas, otherwise returns false.
Notes
Database tables may not support changing table schemas for many reasons. For example, a table may support changing schema if the database is opened in read-write mode, but the same table will not support changing schema if the database is opened in read-only mode.
If some tables support changing schemas and others don't, the property returns true.
To check if a particular table supports changing schema, use Table.CanDesign. To change the table schema, use Table.Design. To rename an item in the table schema, use Table.Rename.
Attempting to change the schema of a table may fail even if the table reports that it supports changing schema and even if the specified changes are supported by the database. For example, attempting to change the schema of a table on a SQL Server database might fail due to insufficient permissions, with the properties reporting that both the database and the table support changing schema in general.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { // check if database supports changing schemas if (!db.CanDesign) app.Log("Root database does not support changing table schemas"); else { app.Log("Root database supports changing table schemas"); // insert new table Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); string inserted = db.Insert("new table", "table", schema); using (Manifold.Table table = db.Search(inserted)) { // check if table supports changing schema if (!table.CanDesign) app.Log("New table does not support changing table schema"); else app.Log("New table supports changing table schema"); } // delete inserted table db.Delete(inserted); } } app.OpenLog(); } // result: Root database supports changing table schemas // ....... New table supports changing table schema
The above example checks if the root database supports changing table schemas, then creates a new table and checks if that table supports changing table schema as well.
15.3. Database.CanInsert
Syntax
bool CanInsert
Return Value
Returns true if the database supports inserting new components, otherwise returns false.
Notes
Databases for some technologies do not support inserting components at all. Databases for other technologies may disable inserting components, for example, if they are opened in read-only mode.
To insert a new component, use Database.Insert.
Attempting to insert a new component may fail even if the database reports that it supports inserting components in general. For example, a database may allow inserting components of some types, but not others.
Examples
See examples for Database.CanDelete.
15.4. Database.CanMigrate
Syntax
bool CanMigrate
Return Value
Returns true if the database supports migrating data from Manifold 8 Enterprise Storages to regular tables, otherwise returns false.
Notes
Manifold 8 Enterprise Storages are sets of tables with binary data used by Manifold 8 to store components in database-neutral format.
To check if a database contains an Enterprise Storage that has not yet been migrated to regular tables, or if that Enterprise Storage has changed after it has been migrated, use Database.IsMigrateNeeded. To migrate an Enterprise Storage to regular tables, use Database.Migrate.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { if (!db.CanMigrate) app.Log("New database does not support migrating Enterprise Storages"); else if (!db.IsMigrateNeeded) app.Log("New database does not contain Enterprise Storage or that Storage has already been migrated"); else app.Log("New database contains Enterprise Storage with changes that have not been migrated"); } app.OpenLog(); } // result: New database does not support migrating Enterprise Storages
The above example creates a new database and checks if it supports migrating data from Enterprise Storages.
15.5. Database.CanRefresh
Syntax
bool CanRefresh
Return Value
Returns true if the database supports refreshing the cached contents of the system mfd_root and mfd_meta tables, otherwise returns false.
Notes
Databases representing connections to database systems like Oracle or SQL Server need to refresh the cached contents of the system mfd_root and mfd_meta tables to acquire changes made by running queries using the native query engine, or by other users remotely.
To refresh the cached contents of the system tables in a database, use Database.Refresh.
Examples
See examples for Database.Refresh.
15.6. Database.CanRename
Syntax
bool CanRename
Return Value
Returns true if the database supports renaming components, otherwise returns false.
Notes
Databases for some technologies do not support renaming components at all. Databases for other technologies may disable renaming components, for example, if they are opened in read-only mode.
To rename a component, use Database.Rename.
Attempting to rename a particular component may fail even if the database reports that it supports renaming components in general. For example, attempting to rename a particular component on a SQL Server database might fail due to insufficient permissions, whereas attempting to rename a different component in the same database would succeed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { if (!db.CanRename) app.Log("Can't rename existing components"); else { try { db.Rename("renamed", "mfd_root"); // will throw app.Log("Renamed component"); } catch (System.Exception e) { app.Log(e.Message); } } } app.OpenLog(); } // result: Can't rename system entity.
The above example tries to rename the system mfd_root table, fails and logs the error message.
The example assumes the root database is opened in read-write mode.
15.7. Database.CanRun
Syntax
bool CanRun
Return Value
Returns true if the database supports running queries, otherwise returns false.
Notes
All databases returned by the current calls in the object model support running queries using at least the Manifold query engine. Callers should check the value returned by Database.CanRun to fail gracefully in case of potential future changes.
To run a query, use Database.Run. To create a compiled query, use Database.RunCompile. To run a compiled query, use Command.Run. To get the schema of the result table of a compiled query, use Command.GetSchema.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { if (!db.CanRun) { app.Log("Can't run queries"); return; } string query = "SELECT Count(*) AS c FROM mfd_root;"; using (Manifold.Table result = db.Run(query)) { string[] fields = new string[] { "c" }; using (Manifold.Sequence sequence = result.SearchAll(fields)) { if (sequence.Fetch()) app.Log(sequence.GetValues()[0].Data.ToString()); } } } app.OpenLog(); } // result: 3
The above example runs the query that counts the number of components and reports the result.
15.8. Database.CanSave
Syntax
bool CanSave
Return Value
Returns true if the database does not automatically save changes to persistent storage until explicitly requested to do so via Database.Save. Returns false if the database automatically saves changes to persistent storage as they occur.
Notes
Databases for MAP files do not automatically save changes to persistent storage until explicitly requested to do so.
Databases for file data sources configured to cache data in .MAPCACHE files do not automatically save changes to persistent storage. Databases for file data sources configured to cache no data usually save changes automatically as they occur.
Databases representing connections to database systems like Oracle or SQL Server save changes automatically as they occur. Additional control in the form of transactions is available via native SQL in Database.Run.
Databases representing connections to web data sources also save changes automatically as they occur. When such databases are configured to cache data in the parent data source, changes to cache data might or might not be saved automatically depending on what the parent data source is.
To check if a database that does not automatically save changes to persistent storage has unsaved changes, use Database.IsSaveNeeded. To check if saving changes will change database format, use Database.IsSaveAsNeeded. To save changes, use Database.Save.
Examples
// tries to read file: c:\data\country.shp static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\country.shp"); connProperties.SetProperty("SourceCacheExternal", true); using (Manifold.Database db = app.CreateDatabase("shp", connProperties.ToJson(), true)) app.Log("Connecting with cache, save is " + (db.CanSave? "manual": "automatic")); connProperties.SetProperty("SourceCacheExternal", false); using (Manifold.Database db = app.CreateDatabase("shp", connProperties.ToJson(), true)) app.Log("Connecting without cache, save is " + (db.CanSave? "manual": "automatic")); app.OpenLog(); } // result: Connecting with cache, save is manual // ....... Connecting without cache, save is automatic
The above example tries to open a SHP file with and without cache, and checks whether the database saves or does not save changes to persistent storage automatically for each mode.
15.9. Database.CanSaveCompact
Syntax
bool CanSaveCompact
Return Value
Returns true if the database supports compacting saves, otherwise returns false. A compacting save is a save that tries to reduce the size of persistent storage without altering data.
Notes
Compacting saves are used as a trade-off to allow quick writes to formats designed in such a way that regular writes are slow. Databases that support compacting saves usually make copies of data on a significant proportion of changes and mark old copies of data as deleted. A compacting save removes old copies of data from the file, reducing the file size.
Most notably, compacting saves are used with SHP files and with standalone DBF files.
To check if a compacting save will recover a significant amount of space (with the measure of "significant" determined by the database), use Database.IsSaveCompactNeeded. To perform a compacting save, use Database.SaveCompact.
Examples
// tries to read file: c:\data\country.shp static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabaseForFile(@"c:\data\country.shp", true)) { if (!db.CanSaveCompact) app.Log("Database does not support compacting saves"); else if (!db.IsSaveCompactNeeded) app.Log("Database supports compacting saves"); else app.Log("Database supports compacting saves and needs compacting"); } app.OpenLog(); } // result: Database supports compacting saves
The above example opens a SHP file and checks if a compacting save will reduce its size.
15.10. Database.Connection
Syntax
string Connection
Return Value
Returns the connection string for the database.
Notes
Connection strings are in JSON format. Connection string items are specific to the database technology. Most technologies use the "Source" item to store the filename, the URL or the database-specific connection string.
To get the technology for the database, use Database.Technology. To get the resolved technology for the database, use Database.TechnologyResolved.
Examples
// tries to read file: c:\data\country.shp static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabaseForFile(@"c:\data\country.shp", true)) app.Log(db.Connection); app.OpenLog(); } // result: { "Source": "c:\\data\\country.shp" }
The above example opens a SHP file and reports the generated connection string.
15.11. Database.CreateExpressionParser
Syntax
ExpressionParser CreateExpressionParser()
Return Value
Returns an expression parser used to create expressions for the database.
Notes
Expressions created by the expression parser returned by this method can reference components in the database by name. They can also access data in arbitrary tables by taking tables as parameters.
A single expression parser can be used to create any number of expressions. There is no need to create a new expression parser for each new expression.
Expression parser objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.ExpressionParser parser = db.CreateExpressionParser()) { Manifold.ValueSet source = app.CreateValueSet(); source.AddValueType("par", typeof(string)); string expr = "(SELECT value FROM mfd_meta WHERE name=par AND property='Folder')"; using (Manifold.Expression expression = parser.CreateExpression(expr, source)) { source[0].Data = "mfd_root"; Manifold.ValueSet result = expression.Evaluate(source); app.Log(result[0].Data.ToString()); } } } app.OpenLog(); } // result: System Data
The above example creates a new expression parser for the root database, creates an expression that retrieves the name of a folder for a component from the system mfd_meta table, then evaluates the expression for the system mfd_root table and reports the result.
15.12. Database.Delete
Syntax
void Delete(string name)
Parameters
name - component name. Case-insensitive.
Notes
The method attempts to delete a component with the specified name.
Attempting to delete a component that does not exist will fail.
Attempting to delete a system component like mfd_root or mfd_meta will fail.
Attempting to delete a component in a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to delete a component without having sufficient permissions will fail.
Deleting a component will not automatically delete other components referencing that component. For example, deleting a table with vector data referenced by a drawing will not delete the drawing.
To check if a database supports deleting components, use Database.CanDelete.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { // delete component named 'result' if it exists string type = db.GetComponentType("result"); if (!string.IsNullOrEmpty(type)) { db.Delete("result"); app.Log("Deleted old component, type: " + type); } // create new component named 'result' string inserted = db.Insert("result", "comments"); app.Log("Inserted new component"); } app.OpenLog(); } // result: Inserted new component // on 2nd run // result: Deleted old component, type: comments // ....... Inserted new component
The above example looks for a component named 'result' and deletes it, if it exists. The example then creates a new component with the same name.
15.13. Database.Design
Syntax
void Design(string name, Schema schema) void Design(string name, Schema schema, PropertySet properties)
Parameters
name - table name. Case-insensitive.
schema - new table schema.
properties - additional details for schema changes.
Notes
The method attempts to change the schema of the table with the specified name.
Attempting to change the schema of a component that does not exist will fail.
Attempting to change the schema of a component that is not a table will fail.
Attempting to change the schema of a system component like mfd_root or mfd_meta will fail.
Attempting to change the schema of a component in a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to change the schema of a component without having sufficient permissions will fail.
The method calls Table.Design on the specified table. If the call succeeds, the method then saves additional details for schema changes specified in the properties parameter to the table properties.
To change the schema of a table without saving details for schema changes specified separately from the schema to the table properties, use Table.Design directly.
For more notes on changing table schema, see Table.Design.
15.14. Database.Export
Syntax
void Export(string name, string technology, string connection)
Parameters
name - name of the component to export or an empty string if the entire database is exported. Case-insensitive.
technology - export technology name, eg, "csv". Case-insensitive.
connection - connection string specifying export location and parameters.
Notes
The method exports the component with the specified name. If the name is an empty string, the method exports the entire database. The destination is determined by the export technology and connection string.
Attempting to export a component that does not exist will fail.
Attempting to export a component of the type not supported by the export technology will fail.
The connection string is in JSON format with items specific to the export technology. Most technologies use the "Source" item to store the filename, the URL or the database-specific connection string.
To export a component or the entire database to a file, determining the technology automatically, use Database.ExportFile. To determine the technology for a file, use Application.GetTechnologyForFile.
Examples
// tries to write file: c:\data\root.csv static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\root.csv"); db.Export("mfd_root", "csv", connProperties.ToJson()); app.Log("Exported mfd_root to CSV"); } app.OpenLog(); } // result: Exported mfd_root to CSV
The above example exports the system mfd_root table to a CSV file.
// tries to write file: c:\data\backup.mxb static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\backup.mxb"); db.Export("", "mxb", connProperties.ToJson()); app.Log("Exported current database to MXB"); } app.OpenLog(); } // result: Exported current database to MXB
The above example exports the opened database to an MXB file.
15.15. Database.ExportFile
Syntax
void Export(string name, string path)
Parameters
name - name of the component to export or an empty string if the entire database is exported. Case-insensitive.
path - path to file, eg, "c:\data.csv".
Notes
The method exports the component with the specified name to the specified path. If the name is an empty string, the method exports the entire database. The export technology is determined automatically from the filename.
Attempting to export a component that does not exist will fail.
Attempting to export a component of the type not supported by the export technology will fail.
To export a component or the entire database using a specific technology and connection string, use Database.Export. To determine the technology for a file, use Application.GetTechnologyForFile.
Examples
// tries to write file: c:\data\root.csv static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { db.ExportFile("mfd_root", @"c:\data\root.csv"); app.Log("Exported mfd_root to CSV"); } app.OpenLog(); } // result: Exported mfd_root to CSV
The above example exports the system mfd_root table to a CSV file.
// tries to write file: c:\data\backup.mxb static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { db.ExportFile("", @"c:\data\backup.mxb"); app.Log("Exported current database to MXB"); } app.OpenLog(); } // result: Exported current database to MXB
The above example exports the opened database to an MXB file.
15.16. Database.GetCache
Syntax
Database GetCache()
Return Value
Returns the database used as cache for the queried database.
Notes
For databases representing connections to web data sources and configured to use cache, the method returns the parent database.
For other databases, the method returns a null reference.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Database cache = db.GetCache()) { if (cache == null) app.Log("Root database does not have cache database attached"); else app.Log("Root database has cache database attached"); } } app.OpenLog(); } // result: Root database does not have cache database attached
The above example checks if the root database has a cache database attached.
15.17. Database.GetChild
Syntax
Database GetChild(string name) Database GetChild(string name, bool connect, bool forceDiscover)
Parameters
name - name of data source component. Case-insensitive.
connect - if true, attempts to open the database of the data source component if it was not already opened; if false, does not attempt to open the database if it was not already opened.
forceDiscover - if true, forces the database of the data source component to completely finish discovery of all available components before the method returns; if false, the database may continue to discover available components progressively in a background thread after the method returns.
Return Value
Returns the database for the specified data source component.
Notes
Calling the method without connect and forceDiscover parameters is equivalent to setting these parameters to true.
If the database of the data source component has already been opened, the connect parameter is ignored.
If the database of the data source component has not been opened and connect is false, the method returns a null reference. The forceDiscover parameter is ignored.
If the database of the data source component has not been opened and connect is true, the method attempts to open the database.
If forceDiscover is true, the method forces the database of the data source component to complete the discovery process before returning. After the discovery process completes, Database.Search is guaranteed to return data for any of the available components, and the mfd_root table lists all available components as well.
If forceDiscover is false, the method allows the database of the data source component to offload the discovery process to a background thread. Until the discovery process completes, Database.Search may fail to return data for some of the available components until they are discovered, and mfd_root may not list some of the available components until they are discovered either.
The forceDiscover parameter should normally be set to true, unless the caller wants to reduce the time it takes to connect to the database and is prepared to deal with the components being discovered progressively in a background thread (for example, waiting until the discovery completes in case the requested component is not yet available).
Calling the method more than once for the same data source component will return the same database, even if the properties of the data source component are changed between calls.
Deleting the data source component with an opened child database automatically deletes the child database, attempting to call Database.GetChild with the name of the deleted component will return a null reference.
Renaming the data source component with an opened child database automatically renames the child database, attempting to call Database.GetChild will return a null reference for the old name and will return the original child database for the new name.
Database objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// tries to access data source component: country static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { Manifold.Database child = db.GetChild("country", false, false); if (child != null) app.Log("Data source has already been opened"); else { child = db.GetChild("country", true, false); // will throw if cannot connect app.Log("Data source is now opened, but might not list all components"); } if (child != null) child.Dispose(); using (child = db.GetChild("country", true, true)) // not supposed to throw app.Log("Data source is now opened and lists all components"); } app.OpenLog(); } // result: Data source is now opened, but might not list all components // ....... Data source is now opened and lists all components // on 2nd run // result: Data source has already been opened // ....... Data source is now opened and lists all components
The above example locates the data source component named 'country' and attempts to open its database with various connection options.
Attempting to open the database of the data source component with forceDiscover set to true forces the discovery process to complete even if the database has already been opened before with the discovery process allowed to proceed progressively in a background thread.
// tries to read file: c:\data\mexico.map static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { // create data source Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\mexico.map"); string conn = connProperties.ToJson(); string inserted = db.Insert("mexico", "datasource"); db.SetProperty(inserted, "Type", "manifold"); db.SetProperty(inserted, "Source", conn); app.Log("Created data source"); // connect to data source using (Manifold.Database child = db.GetChild(inserted)) { if (child != null) app.Log("Connected to data source"); } // rename data source string renamed = db.Rename("mexico_new", inserted); app.Log("Renamed data source"); // access data source without connecting using (Manifold.Database child = db.GetChild(renamed, false, false)) { if (child != null) app.Log("Child database remains opened after rename"); } // delete data source db.Delete(renamed); app.Log("Deleted data source"); // check if child database is still there using (Manifold.Database child = db.GetChild(renamed, false, false)) { if (child == null) app.Log("Child database has been removed"); else app.Log("Child database has been left opened"); } } app.OpenLog(); } // result: Created data source // ....... Connected to data source // ....... Renamed data source // ....... Child database remains opened after rename // ....... Deleted data source // ....... Child database has been removed
The above example creates a new data source for a MAP file, opens its database, and then renames and deletes the data source checking if the database is still opened after each action.
15.18. Database.GetComponentType
Syntax
string GetComponentType(string name)
Parameters
name - name of the component. Case-insensitive.
Return Value
Returns type of the component. Returns an empty string if the component does not exist.
Notes
The method locates a component with the specified name and returns its type.
If the database is in the process of discovering components, the method may fail to return data for components that has not yet been discovered. See Application.CreateDatabase for details.
All databases contain at least the mfd_root and mfd_meta system tables.
To access data of a table component, use Database.Search.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) app.Log(db.GetComponentType("mfd_root")); app.OpenLog(); } // result: table
The above example reports the type of the system mfd_root table.
15.19. Database.GetProperties
Syntax
PropertySet GetProperties(string name) PropertySet GetProperties(string name, PropertySet properties)
Parameters
name - name of the component. Case-insensitive.
properties - names of the properties to read.
Return Value
Returns the values of the specified properties or the values of all properties for the specified component.
Notes
The method returns the values of properties from the system mfd_meta table.
If the properties parameter is not passed, the method retrieves the values of all properties for the specified component.
If the properties parameter is passed, the method retrieves only the values of the properties specified in that parameter. If a specific property does not exist, it is included in the result with the value of an empty string.
If the specified component does not exist, the method will still return the values of the properties stored in the mfd_meta table.
To get the value of a single property, use Database.GetProperty. To set the value of a property, use Database.SetProperty. To set the values of multiple properties, use Database.SetProperties.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) app.Log(db.GetProperties("mfd_meta").ToJson()); app.OpenLog(); } // result: { "Folder": "System Data" }
The above example reports the values of all properties for the system mfd_meta table.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Date", ""); properties.SetProperty("Description", ""); properties.SetProperty("Folder", ""); app.Log(db.GetProperties("mfd_meta", properties).ToJson()); } app.OpenLog(); } // result: { "Date": "", "Description": "", "Folder": "System Data" }
The above example reports the values of several specific properties for the system mfd_meta table.
15.20. Database.GetProperty
Syntax
string GetProperty(string name, string prop)
Parameters
name - name of the component. Case-insensitive.
prop - name of the property. Case-insensitive.
Return Value
Returns the value of the specified property for the specified component.
Notes
The method returns the value of the specified property from the system mfd_meta table.
If the specified property does not exist, the method returns an empty string.
If the specified component does not exist, the method will still return the value of the specified property stored in the mfd_meta table, if it exists.
To get the values of multiple properties or the values of all properties for the specified component, use Database.GetProperties. To set the value of a property, use Database.SetProperty. To set the values of multiple properties, use Database.SetProperties.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) app.Log(db.GetProperty("mfd_meta", "Folder")); app.OpenLog(); } // result: System Data
The above example reports the name of the folder for the system mfd_meta table.
15.21. Database.Insert
Syntax
string Insert(string name, string type) string Insert(string name, string type, Schema schema) string Insert(string name, string type, Schema schema, PropertySet properties)
Parameters
name - component name. Case-insensitive.
type - component type. Case-insensitive.
schema - schema for a new table component.
properties - additional details for schema objects.
Return Value
Returns the final name of a new component with which it was inserted.
The final name may differ from the requested name. For example, a database representing a connection to SQL Server may alter the requested name for a new table to include the prefix of the current database schema.
Notes
The method attempts to insert a component with the specified name of the specified type.
Calling the method without the schema parameter creates components other than tables. Attempting to use the method to insert a new table without the schema parameter will fail.
Calling the method with the schema parameter creates all types of components, including tables. If the method is used to insert a table, the passed schema must include at least one field. If the method is used to insert a component other than a table, the schema parameter is ignored.
Attempting to insert a component with the name of an existing component will fail.
Attempting to insert a component into a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to insert a component without having sufficient permissions will fail.
To check if a database supports inserting components, use Database.CanInsert. To check if a database will likely support changing the schema of a table after it has been inserted, use Database.CanDesign. To change the schema of a table after it has been inserted, use Table.Design.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { // create a new comments component with empty text db.Insert("new_comments", "comments"); app.Log("Created new comments component"); // create a new table component Manifold.Schema schema = app.CreateSchema(); schema.AddField("mfd_id", "int64"); schema.AddIndex("mfd_id_x", "btree", new string[] { "mfd_id" }); schema.AddField("value", "nvarchar"); db.Insert("new_table", "table", schema); app.Log("Created new table component"); } app.OpenLog(); } // result: Created new comments component // ....... Created new table component
The above example inserts a new comments component and a new table component.
15.22. Database.IsMigrateNeeded
Syntax
bool IsMigrateNeeded
Return Value
Returns true if the database supports migrating data from Manifold 8 Enterprise Storages to regular tables and if the database contains an Enterprise Storage that has not been migrated or that has changed after being migrated. Returns false if the database does not support migrating data from Manifold 8 Enterprise Storages or if the database does not contain an Enterprise Storage or if the Enterprise Storage has already been migrated and has not changed after that.
Notes
Manifold 8 Enterprise Storages are sets of tables with binary data used by Manifold 8 to store components in database-neutral format.
To check if a database supports migrating data from an Enterprise Storage, use Database.CanMigrate. To migrate an Enterprise Storage to regular tables, use Database.Migrate.
Examples
See examples for Database.CanMigrate.
15.23. Database.IsReadOnly
Syntax
bool IsReadOnly
Return Value
Returns true if the database has been opened in read-only mode, otherwise returns false.
Notes
Databases opened in read-only mode disallow adding, changing or deleting components, including via running queries using the Manifold query engine. Running queries using the native query engine specific to the database can still change data.
Attempting to change data in a database may fail even if the database has not been opened in read-only mode. For example, attempting to update records in a table on a SQL Server database might fail due to insufficient permissions.
Examples
// tries to read file: c:\data\country.shp static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\country.shp"); using (Manifold.Database db = app.CreateDatabase("shp", connProperties.ToJson(), true)) app.Log("Connecting without flags, database is " + (db.IsReadOnly? "read-only": "writable")); connProperties.SetProperty("SourceReadOnly", true); using (Manifold.Database db = app.CreateDatabase("shp", connProperties.ToJson(), true)) app.Log("Connecting with read-only flag, database is " + (db.IsReadOnly? "read-only": "writable")); app.OpenLog(); } // result: Connecting without flags, database is writable // ....... Connecting with read-only flag, database is read-only
The above example tries to open a SHP file with and without the read-only flag, and checks whether the database is read-only.
15.24. Database.IsSaveAsNeeded
Syntax
bool IsSaveAsNeeded
Return Value
Returns true if the database does not automatically save changes to persistent storage until explicitly requested to do so via Database.Save and if saving to the original storage will change its format. Returns false if the database automatically saves changes to persistent storage as they occur or if saving to the original storage will not change its format.
Notes
Saving changes to persistent storage may sometimes change its format. For example, saving changes to a MAP file created by Manifold 8 will upgrade its format to Manifold 9 and make the file unreadable in Manifold 8. If saving changes to the original storage will radically change its format in this way, the property will return true.
Saving changes to a different file will always leave the original file intact.
To check if a database does not automatically save changes to persistent storage, use Database.CanSave. To check if a database has unsaved changes, use Database.IsSaveNeeded. To save changes, use Database.Save.
For a brief rundown on which databases save changes to persistent storage automatically and which do not, see notes for Database.CanSave.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { if (!db.CanSave) app.Log("New database saves changes automatically"); else if (!db.IsSaveAsNeeded) app.Log("Saving new database will not change its format"); else app.Log("Saving new database will change its format"); } app.OpenLog(); } // result: Saving new database will not change its format
The above example creates a new database and checks if it uses old or new format.
15.25. Database.IsSaveCompactNeeded
Syntax
bool IsSaveCompactNeeded
Return Value
Returns true if the database supports compacting saves and if attempting to perform a compacting save will recover a significant amount of space, otherwise returns false. A compacting save is a save that tries to reduce the size of persistent storage without altering data.
Notes
Compacting saves are used as a trade-off to allow quick writes to formats designed in such a way that regular writes are slow. Databases that support compacting saves usually make copies of data on a significant proportion of changes and mark old copies of data as deleted. A compacting save removes old copies of data from the file, reducing the file size.
Most notably, compacting saves are used with SHP files and with standalone DBF files.
The amount of potentially recovered space that is considered to be significant depends on the database. SHP and DBF files use two quotas - if the amount of space that would be recovered by a compacting save is less than the pre-defined number of bytes or if it is less than the pre-defined percentage of a total file size, the database reports that the amount of space to recover is too small and that the compacting save is not needed.
To check if a database supports compacting saves, use Database.CanSaveCompact. To perform a compacting save, use Database.SaveCompact.
Examples
See examples for Database.CanSaveCompact.
15.26. Database.IsSaveNeeded
Syntax
bool IsSaveNeeded
Return Value
Returns true if the database does not automatically save changes to persistent storage until explicitly requested to do so via Database.Save and if there are unsaved changes. Returns false if the database automatically saves changes to persistent storage as they occur or if there are no unsaved changes.
Notes
The amount of changes does not matter. If the database does not save changes automatically and there are any unsaved changes, the property will return true.
To check if a database does not automatically save changes to persistent storage, use Database.CanSave. To check if saving changes will change database format, use Database.IsSaveAsNeeded. To save changes, use Database.Save.
For a brief rundown on which databases save changes to persistent storage automatically and which do not, see notes for Database.CanSave.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { if (!db.CanSave) app.Log("New database saves changes automatically"); else if (!db.IsSaveNeeded) app.Log("New database does not have unsaved changes"); else app.Log("New database has unsaved changes"); } app.OpenLog(); } // result: New database has unsaved changes
The above example creates a new database and checks if it has unsaved changes.
15.27. Database.Migrate
Syntax
void Migrate()
Notes
The method migrates data from the Manifold 8 Enterprise Storage in the database to regular tables.
Manifold 8 Enterprise Storages are sets of tables with binary data used by Manifold 8 to store components in database-neutral format. Migrating data from an Enterprise Storage unpacks binary data into regular tables with fields and records that can be accessed using queries. The Enterprise Storage is left unchanged.
If the database does not support migrating data from Enterprise Storages, the method does nothing.
If the database does not contain an Enterprise Storage, the method does nothing.
If the database contains an Enterprise Storage which has already been migrated and has not changed after that, the method does nothing.
Attempting to migrate data from an Enterprise Storage might fail due to insufficient permissions.
To check if a database supports migrating data from Enterprise Storages, use Database.CanMigrate. To check if a database contains an Enterprise Storage that has not yet been migrated to regular tables, or if that Enterprise Storage has changed after it has been migrated, use Database.IsMigrateNeeded.
Examples
// tries to connect to local instance of SQL Server: (LOCALDB) static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"server=(LOCALDB);integrated security=sspi;"); using (Manifold.Database db = app.CreateDatabase("sqlserver", connProperties.ToJson(), true)) { if (!db.CanMigrate) app.Log("Database does not support migrating Enterprise Storages"); else if (!db.IsMigrateNeeded) app.Log("Database does not contain Enterprise Storage or that Storage has already been migrated"); else { app.Log("Database contains Enterprise Storage with changes that have not been migrated"); db.Migrate(); app.Log("Migration complete"); } } app.OpenLog(); } // result: Database does not contain Enterprise Storage or that Storage has already been migrated
The above example connects to a SQL Server database, checks if it contains an Enterprise Storage and attempts to migrate data from that storage to regular tables.
15.28. Database.Refresh
Syntax
void Refresh()
Notes
The method refreshes the cached contents of the system mfd_root and mfd_meta tables.
Databases representing connections to database systems like Oracle or SQL Server need to refresh the cached contents of the system mfd_root and mfd_meta tables to acquire changes made by running queries using the native query engine, or by other users remotely.
If the database does not support refreshing the cached contents of the system tables, the method does nothing.
To check if a database supports refreshing the cached contents of the system tables, use Database.CanRefresh.
Examples
// tries to connect to local instance of SQL Server: (LOCALDB) static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"server=(LOCALDB);integrated security=sspi;"); using (Manifold.Database db = app.CreateDatabase("sqlserver", connProperties.ToJson(), true)) { if (!db.CanRefresh) app.Log("Database does not support refreshing cached contents of system tables"); else if (db.GetComponentType("dbo.test") != "") app.Log("Database already contains test component"); else { app.Log("Inserting test component via native query engine"); db.Run("CREATE TABLE test (id INT);"); if (db.GetComponentType("dbo.test") != "") app.Log("Inserted component available immediately"); else { app.Log("Inserted component not available immediately, refreshing system tables"); db.Refresh(); if (db.GetComponentType("dbo.test") != "") app.Log("Inserted component available after refresh"); else app.Log("Inserted component not available after refresh"); } db.Run("DROP TABLE test;"); } } app.OpenLog(); } // result: Inserting test component via native query engine // ....... Inserted component not available immediately, refreshing system tables // ....... Inserted component available after refresh
The above example connects to a SQL Server database, inserts a test component by running a query using the native query engine, then refreshes the system tables to make the inserted component available for use in Manifold.
15.29. Database.Rename
Syntax
string Rename(string nameNew, string name)
Parameters
nameNew - new name. Case-insensitive.
name - component name. Case-insensitive.
Return Value
Returns the final name of a new component to which it was renamed.
Notes
The method attempts to rename a component.
The final name may differ from the requested new name. For example, a database representing a connection to SQL Server may alter the requested new name for a table to include the prefix of the current database schema.
Attempting to rename a component to the name of an existing component will fail.
Attempting to rename a system component like mfd_root or mfd_meta will fail.
Attempting to rename a component in a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to rename a component without having sufficient permissions will fail.
Renaming a component will not automatically adjust references to that component in other components. For example, renaming a table with vector data referenced by a drawing will not adjust the properties of the drawing to use the new name of the table.
To check if a database supports renaming components, use Database.CanRename.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { // insert new component string inserted = db.Insert("example", "comments"); app.Log("Inserted new component: " + inserted); // rename component string renamed = db.Rename("example renamed", inserted); app.Log("Renamed component to: " + renamed); } app.OpenLog(); } // result: Inserted new component: example // ....... Renamed component to: example renamed
The above example inserts a new component and renames it.
15.30. Database.Run
Syntax
Table Run(string text) Table Run(string text, ValueSet values)
Parameters
text - query text.
values - query parameter values.
Return Value
Returns the result table of the query.
Notes
The method attempts to run a query with the specified text.
The values parameter contains optional parameter values for the query. If the query uses no parameters, the passed values are ignored. If the query uses parameters and one or more of the parameters is not passed, the method will fail.
For action queries, the returned table contains a single value representing the number of affected records.
All databases support running queries using the Manifold query engine. Some databases, such as databases representing connections to SQL Server or PostgreSQL, also support running queries using the native query engine specific to the database. In the latter databases, the method first inspects the text of the query and looks for the '-- $manifold$' directive. If the text includes the directive, the method runs the query using the Manifold query engine, otherwise it runs the query using the native query engine specific to the database.
To check if a database supports running queries, use Database.CanRun. To compile a query for repeated runs, use Database.RunCompile. To run a compiled query, use Command.Run. To get the schema of the result table of a compiled query, use Command.GetSchema.
When running a query multiple times, consider using a compiled query to improve performance. When running a query with parameters multiple times, consider passing parameter values using a locked value set. To create a locked value set, use ValueSet.CreateLocked.
Table objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT * INTO [copy] FROM [mfd_root]"; using (Manifold.Table table = db.Run(text)) { using (Manifold.Sequence sequence = table.SearchAll(new string[] { "result" })) { sequence.Fetch(); // fetch the only record app.Log(sequence.GetValues()[0].Data.ToString()); } } } app.OpenLog(); } // result: 4
The above example runs an action query to create a copy of the mfd_root table and reports the number of affected records returned by the query.
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT * FROM [mfd_root]"; using (Manifold.Table table = db.Run(text)) { using (Manifold.Sequence sequence = table.SearchAll(new string[] { "name", "type" })) { if (sequence != null) { while (sequence.Fetch()) { Manifold.ValueSet values = sequence.GetValues(); app.Log(string.Format("{0} : {1}", values[0].Data, values[1].Data)); } } } } } app.OpenLog(); } // result: mfd_root : table // ....... mfd_meta : table // ....... Script : script
The above example runs a SELECT query to list all components in the mfd_root table and reports the result.
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT * FROM [mfd_root] WHERE StringToLowerCase([type]) = @lowercaseType"; Manifold.ValueSet parameters = app.CreateValueSet(); parameters.AddValue("lowercaseType", "script"); using (Manifold.Table table = db.Run(text, parameters)) { using (Manifold.Sequence sequence = table.SearchAll(new string[] { "name", "type" })) { if (sequence != null) { while (sequence.Fetch()) { Manifold.ValueSet values = sequence.GetValues(); app.Log(string.Format("{0} : {1}", values[0].Data, values[1].Data)); } } } } } app.OpenLog(); } // result: Script : script
The above example runs a SELECT query to list all script components in the mfd_root table passing the desired component type as a parameter, and reports the result.
15.31. Database.RunCompile
Syntax
Command RunCompile(string text) Command RunCompile(string text, ValueSet values)
Parameters
text - query text.
values - query parameter values.
Return Value
Returns a new compiled query with the specified text and parameters.
Notes
The method attempts to compile a query with the specified text.
The values parameter contains optional parameter values for the query. If the query uses no parameters, the passed values are ignored. If the query uses parameters and one or more of the parameters is not passed, the method will fail.
All databases support running compiled queries using the Manifold query engine. Some databases, such as databases representing connections to SQL Server or PostgreSQL, also support running compiled queries using the native query engine specific to the database. In the latter databases, the method first inspects the text of the query and looks for the '-- $manifold$' directive. If the text includes the directive, the method compiles the query using the Manifold query engine, otherwise it compiles the query using the native query engine specific to the database.
Some databases support running ad-hoc queries using the native query engine specific to the database, but not compiling them for repeated runs. Attempting to compile a query using the native query engine on such a database will return a null reference.
To check if a database supports running queries, use Database.CanRun. To run an ad-hoc query, use Database.Run. To run a compiled query, use Command.Run. To get the schema of the result table of a compiled query, use Command.GetSchema.
Command objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "VALUES (@p), (@q)"; Manifold.ValueSet parameters = app.CreateValueSet(); parameters.AddValueType("p", "float64"); parameters.AddValueType("q", "float64"); using (Manifold.Command command = db.RunCompile(text, parameters)) app.Log("Compiled query with parameters"); } app.OpenLog(); } // result: Compiled query with parameters
The above example compiles a query with two numeric parameters.
15.32. Database.Save
Syntax
void Save() void Save(string path)
Parameters
path - path to save to. May be empty.
Notes
Calling the method without parameters attempts to save changes to the current path.
Calling the method with parameters attempts to save changes to the specified path. If path is an empty string, the method attempts to save changes to the current path.
If the database saves changes automatically, the method does nothing.
Attempting to save a database may fail due to insufficient space on either the target drive or due to insufficient space on the temp drive. The amount of free space required to save depends on the database.
Attempting to save a database to a new path may fail due to insufficient permissions.
To check if a database does not automatically save changes to persistent storage, use Database.CanSave. To check if a database has unsaved changes, use Database.IsSaveNeeded. To check if saving changes will change database format, use Database.IsSaveAsNeeded.
For a brief rundown on which databases save changes to persistent storage automatically and which do not, see notes for Database.CanSave.
Examples
// tries to write file: c:\data\test2.map // tries to write file: c:\data\test3.map static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { app.Log("Created new database"); // save database db.Save(@"c:\data\test2.map"); app.Log(@"Saved to c:\data\test2.map"); // insert a new component db.Insert("example", "comments"); app.Log("Inserted new component"); // save database to a new filename db.Save(@"c:\data\test3.map"); app.Log(@"Saved to c:\data\test3.map"); } app.OpenLog(); } // result: Created new database // ....... Saved to c:\data\test2.map // ....... Inserted new component // ....... Saved to c:\data\test3.map
The above example creates a new temporary MAP file, saves it, then adds a new component and saves the MAP file with a new name. After the example finishes, the first file should contain only the system tables, while the second file should also contain a comments component.
15.33. Database.SaveCompact
Syntax
void SaveCompact() void SaveCompact(string path)
Parameters
path - path to perform a compacting save to. May be empty. A compacting save is a save that tries to reduce the size of persistent storage without altering data.
Notes
Calling the method without parameters attempts to perform a compacting save in the current path.
Calling the method with parameters attempts to perform a compacting save with the specified path. If path is an empty string, the method attempts to perform a compacting save in the current path.
If the database does not support compacting saves, the method does nothing.
The method will perform a compacting save even if the database reports that such a save will recover an insignificant amount of space.
Compacting saves are used as a trade-off to allow quick writes to formats designed in such a way that regular writes are slow. Databases that support compacting saves usually make copies of data on a significant proportion of changes and mark old copies of data as deleted. A compacting save removes old copies of data from the file, reducing the file size.
Most notably, compacting saves are used with SHP files and with standalone DBF files.
To check if a database supports compacting saves, use Database.CanSaveCompact. To check if a compacting save will recover a significant amount of space (with the measure of "significant" determined by the database), use Database.IsSaveCompactNeeded.
Examples
// tries to read file: c:\data\country.shp static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabaseForFile(@"c:\data\country.shp", true)) { if (!db.CanSaveCompact) app.Log("Database does not support compacting saves"); else if (!db.IsSaveCompactNeeded) app.Log("Database supports compacting saves"); else { app.Log("Database supports compacting saves and needs compacting"); db.SaveCompact(); app.Log("Performed compacting save"); } } app.OpenLog(); } // result: Database supports compacting saves and needs compacting // ....... Performed compacting save // on 2nd run // result: Database supports compacting saves
The above example opens a SHP file and performs a compacting save if the file reports that such a save will reduce its size significantly.
15.34. Database.Search
Syntax
Table Search(string name)
Parameters
name - name of a table component.
Return Value
Returns the table with the specified name. Returns a null reference if the table does not exist.
Notes
The method locates a table component with the specified name.
Attempting to use the method with a component other than a table will return a null reference.
If the database is in the process of discovering components, the method may fail to return data for components that has not yet been discovered. See Application.CreateDatabase for details.
All databases contain at least the mfd_root and mfd_meta system tables.
To get the type of a component or check if a component exists, use Database.GetComponentType.
Table objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) { Manifold.Schema schema = table.GetSchema(); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(field.Name); } } app.OpenLog(); } // result: mfd_id // ....... Name // ....... Type
The above example opens the mfd_root table and lists its fields.
15.35. Database.SetProperties
Syntax
void SetProperties(string name, PropertySet properties)
Parameters
name - name of the component. Case-insensitive.
properties - properties to set.
Notes
The method writes the values of the specified properties to the system mfd_meta table. If the value of a specific property is an empty string, that property is deleted.
If the specified component does not exist, the method will still write the values of the specified properties to the mfd_meta table.
To get the value of a property, use Database.GetProperty. To get the values of multiple properties or the values of all properties for the specified component, use Database.GetProperties. To set the value of a single property, use Database.SetProperty.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Description", "Changed at " + System.DateTime.Now.ToShortDateString()); properties.SetProperty("Folder", "Custom"); db.SetProperties("script", properties); app.Log("Script description: " + db.GetProperty("script", "Description")); } app.OpenLog(); } // result: Script description: Changed at 5/22/2017
The above example sets the folder and the description of a script component and reports the result.
15.36. Database.SetProperty
Syntax
void SetProperty(string name, string prop, string value)
Parameters
name - name of the component. Case-insensitive.
prop - name of the property. Case-insensitive.
value - value of the property.
Notes
The method writes the value of the specified property to the system mfd_meta table. If the value of the property is an empty string, the property is deleted.
If the specified property does not exist, the method does nothing.
If the specified component does not exist, the method will still write the value of the specified property to the mfd_meta table.
To get the value of a property, use Database.GetProperty. To get the values of multiple properties or the values of all properties for the specified component, use Database.GetProperties. To set the values of multiple properties, use Database.SetProperties.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { db.SetProperty("script", "Folder", "Custom"); app.Log("Script folder: " + db.GetProperty("script", "Folder")); } app.OpenLog(); } // result: Script folder: Custom
The above example sets the folder of a script component and reports the result.
15.37. Database.Technology
Syntax
string Technology
Return Value
Returns the technology for the database.
Notes
To get the connection string for the database, use Database.Connection. To get the resolved technology for the database, use Database.TechnologyResolved.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) app.Log(db.Technology); app.OpenLog(); } // result: manifold
The above example reports the technology of the root database.
15.38. Database.TechnologyResolved
Syntax
string TechnologyResolved
Return Value
Returns the resolved technology for the database.
Notes
Databases with generic technologies like ODBC attempt to resolve the specific technology of the database they connect to. The resolved technology is returned via this property.
To get the connection string for the database, use Database.Connection. To get the generic technology for the database, use Database.Technology.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string resolved = db.TechnologyResolved; if (string.IsNullOrEmpty(resolved)) resolved = "<NULL>"; app.Log(resolved); } app.OpenLog(); } // result: <NULL>
The above example reports the resolved technology of the root database (none, because the root database is a MAP file and not a generic connection like ODBC).
16. Expression
16.1. Expression.Evaluate
Syntax
ValueSet Evaluate() ValueSet Evaluate(ValueSet source)
Parameters
source - parameter values.
Return Value
Returns expression results evaluated for the specified parameters.
Notes
The method evaluates the expression for the specified parameter values.
If source is not provided, the values of all expression parameters are assumed to be NULL. If source does not include the value of a specific expression parameter, that value is assumed to be NULL. Values in source that do not correspond to any of the expression parameters are ignored.
The same expression object can be used to evaluate data from multiple threads simultaneously.
Examples
// print object, print <NULL> for null reference static string PrintNull(object o) { return o == null? "<NULL>": o.ToString(); } // try evaluating expression static void TryEvaluate(Manifold.Application app, Manifold.Expression expression, object a, object b) { string prefix = "a = " + PrintNull(a) + ", b = " + PrintNull(b); try { Manifold.ValueSet source = expression.GetSource(); source[0].Data = a; source[1].Data = b; Manifold.ValueSet target = expression.Evaluate(source); app.Log(prefix + ", result: " + PrintNull(target[0].Data)); } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.ExpressionParser parser = app.CreateExpressionParser()) { Manifold.ValueSet source = app.CreateValueSet(); source.AddValueType("a", typeof(int)); source.AddValueType("b", typeof(int)); using (Manifold.Expression expression = parser.CreateExpression("a * b", source)) { TryEvaluate(app, expression, 5, null); TryEvaluate(app, expression, 5, 6); TryEvaluate(app, expression, 5, "abc"); } } app.OpenLog(); } // result: a = 5, b = <NULL>, result: <NULL> // ....... a = 5, b = 6, result: 30 // ....... a = 5, b = abc, result: <NULL>
The above example creates an expression, then tries to evaluate it with different parameter values.
// class for evaluating geometry functions class GeometryFuncs { private Manifold.Expression ExprBuffer; // set up geometry functions public GeometryFuncs(Manifold.Application app) { using (Manifold.ExpressionParser parser = app.CreateExpressionParser()) { Manifold.ValueSet source = app.CreateValueSet(); source.AddValueType("geom", typeof(Manifold.Geom)); source.AddValueType("radius", typeof(double)); source.AddValueType("tolerance", typeof(double)); ExprBuffer = parser.CreateExpression("GeomBuffer(geom, radius, tolerance)", source); } } // evaluate buffer public Manifold.Geom Buffer(Manifold.Geom geom, double radius, double tolerance) { Manifold.ValueSet source = ExprBuffer.GetSource(); source[0].Data = geom; source[1].Data = radius; source[2].Data = tolerance; Manifold.ValueSet target = ExprBuffer.Evaluate(source); return target[0].Data as Manifold.Geom; } // implementation of IDisposable is left out }; static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; GeometryFuncs funcs = new GeometryFuncs(app); // create point geom Manifold.Geom geom; using (Manifold.GeomBuilder builder = app.CreateGeomBuilder()) { builder.StartGeomPoint(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 2)); builder.EndBranch(); geom = builder.EndGeom(); } // compute buffer Manifold.Geom buffer = funcs.Buffer(geom, 5, 0); app.Log(buffer.Coords.Count.ToString()); app.OpenLog(); } // result: 33
The above example creates a helper class to evaluate buffers using expressions, then computes a buffer for a point geom and reports the number of coordinates in the buffer.
16.2. Expression.GetSource
Syntax
ValueSet GetSource()
Return Value
Returns expression parameters.
Notes
The returned ValueSet object includes parameter values referenced by the expression.
The returned object can be used to pass data to the expression using Expression.Evaluate.
Each call to the method returns a new object.
Examples
// list values static string ListValues(Manifold.ValueSet values) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (Manifold.Value value in values) { if (builder.Length > 0) builder.Append(", "); builder.Append(value.Name); } return builder.ToString(); } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.ExpressionParser parser = app.CreateExpressionParser()) { Manifold.ValueSet source = app.CreateValueSet(); source.AddValueType("a", typeof(string)); // not used source.AddValueType("b", typeof(int)); // not used source.AddValueType("c", typeof(string)); // used using (Manifold.Expression expression = parser.CreateExpression("c & 'x'", source)) { app.Log("Expression: " + expression.Text); app.Log("Source: " + ListValues(expression.GetSource())); app.Log("Target: " + ListValues(expression.GetTarget())); } } app.OpenLog(); } // result: Expression: c & 'x' // ....... Source: c // ....... Target: result
The above example creates an expression parser and an expression, then reports the text of the expression and the names of parameter and result values. Creating an expression automatically detects and removes unused parameters.
16.3. Expression.GetTarget
Syntax
ValueSet GetTarget()
Return Value
Returns expression results.
Notes
The returned ValueSet object includes result values returned by the expression. Most expressions return a single result value.
Each call to the method returns a new object.
Examples
See examples for Expression.GetSource.
16.4. Expression.Text
Syntax
string Text
Return Value
Returns expression text.
Notes
The returned value is the exact text used to create the expression, together with comments and whitespace.
Examples
See examples for Expression.GetSource.
17. ExpressionParser
17.1. ExpressionParser.CreateExpression
Syntax
Expression CreateExpression(string text) Expression CreateExpression(string text, ValueSet source)
Parameters
source - expression parameters.
Return Value
Returns a new expression with the specified text and parameters.
Notes
If the expression parser has a context database, the expression can reference components stored on that database or on child databases of that database by name. If the component referenced by the expression does not exist when the expression is created, the method will fail.
The source parameter has to include all parameters used by the expression along with their types. Table parameters have to be set to values that describe their schemas. If the expression uses parameters and source is not provided, the method will fail. If the expression uses a parameter that is not in source, the method will fail. If the expression uses a parameter that is included in source without an associated type, the method will fail. If the expression uses a table parameter that is included in source without an associated table value, the method will fail.
The returned expression object will only use parameters referenced in the expression text.
Expression objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// list values static string ListValues(Manifold.ValueSet values) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (Manifold.Value value in values) { if (builder.Length > 0) builder.Append(", "); builder.Append(value.Name); } return builder.ToString(); } // try creating expression static void TryCreateExpression(Manifold.Application app, string text, Manifold.ValueSet values) { string prefix = "{ " + text + " }"; try { using (Manifold.ExpressionParser parser = app.CreateExpressionParser()) { using (Manifold.Expression expression = parser.CreateExpression(text, values)) app.Log(prefix + ", used parameters: " + ListValues(expression.GetSource())); } } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet source = app.CreateValueSet(); source.AddValueType("a", typeof(int)); source.AddValueType("s", typeof(string)); TryCreateExpression(app, "a+5", source); TryCreateExpression(app, "StringToUpperCase(s)", source); TryCreateExpression(app, "a+s", source); TryCreateExpression(app, "a+b", source); app.OpenLog(); } // result: { a+5 }, used parameters: a // ....... { StringToUpperCase(s) }, used parameters: s // ....... { a+s }, error: '+': Type mismatch. // ....... { a+b }, error: 'b': Unknown name.
The above example creates an expression parser and tries to create various expressions reporting results.
18. Geom
18.1. Geom.Branches
Syntax
Geom.BranchSet Branches
Return Value
Returns branches of the geom value.
Notes
A geom value contains at least one branch. In an area geom value, the first coordinate of each branch coincides with the last coordinate. The minimum number of coordinates in a branch is 1 for a point geom value, 2 for a line geom value and 3 for an area geom value.
Geom values of all types can contain multiple branches.
Branches of normalized area geom values are grouped by shape. Within each shape the single outer branch is followed by one or more inner branches.
To normalize an area geom value, use an Expression object with an appropriate query expression.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 1)); builder.EndBranch(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 3)); builder.AddCoord(new Manifold.Point<double>(2, 3)); builder.AddCoord(new Manifold.Point<double>(3, 4)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Branches.Count.ToString()); app.OpenLog(); } // result: 2
The above example composes a geom value and reports the number of branches.
18.2. Geom.Coords
Syntax
Geom.CoordSet Coords
COM languages:
Geom.CoordSet CoordObjs
Return Value
Returns 2d coordinates of the geom value.
Notes
The coordinates of a geom value are grouped by branch.
In an area geom value, the first coordinate of each branch coincides with the last coordinate.
The 2d coordinates are available for both 2d and 3d geom values. To access the 3d coordinates of a 3d geom value, use Geom.Coord3s.
To access the 2d coordinates of a specific branch, use Geom.Branch.Coords.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 1)); builder.EndBranch(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 3)); builder.AddCoord(new Manifold.Point<double>(2, 3)); builder.AddCoord(new Manifold.Point<double>(3, 4)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); Manifold.Geom.CoordSet coords = geom.Coords; for (int index = 0; index < coords.Count; ++index) app.Log(coords[index].ToString()); app.OpenLog(); } // result: [ 1, 1 ] // ....... [ 2, 1 ] // ....... [ 1, 3 ] // ....... [ 2, 3 ] // ....... [ 3, 4 ]
The above example composes a geom value and reports the coordinates.
18.3. Geom.Coord3s
Syntax
Geom.Coord3Set Coord3s
COM languages:
Geom.Coord3Set Coord3Objs
Return Value
Returns 3d coordinates of the geom value. Returns a null reference if the geom value is 2d.
Notes
The coordinates of a geom value are grouped by branch.
In an area geom value, the first coordinate of each branch coincides with the last coordinate.
To access the 3d coordinates of a specific branch, use Geom.Branch.Coord3s.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(1, 2, 3)); builder.AddCoord3(new Manifold.Point3<double>(4, 5, 6)); builder.AddCoord3(new Manifold.Point3<double>(7, 8, 9)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); Manifold.Geom.CoordSet coords = geom.Coords; Manifold.Geom.Coord3Set coord3s = geom.Coord3s; for (int index = 0; index < coords.Count; ++index) app.Log(string.Format("{0} : {1}", coords[index], coord3s[index])); app.OpenLog(); } // result: [ 1, 2 ] : [ 1, 2, 3 ] // ....... [ 4, 5 ] : [ 4, 5, 6 ] // ....... [ 7, 8 ] : [ 7, 8, 9 ]
The above example composes a 3d geom value and reports both the 2d and 3d coordinates.
18.4. Geom.Curves
Syntax
Geom.CurveSet Curves
Return Value
Returns the curves of the geom value. Returns a null reference if the geom value contains no curves.
Notes
The last curve of each branch is ignored in computations and is set to a straight line segment.
To access the curves of a specific branch, use Geom.Branch.Curves.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(5, 0)); builder.AddCoord(new Manifold.Point<double>(6, 0)); builder.EndBranch(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveCircle(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); Manifold.Geom.CurveSet curves = geom.Curves; for (int index = 0; index < curves.Count; ++index) app.Log(curves[index].ToString()); app.OpenLog(); } // result: Manifold.Curve // ....... Manifold.Curve // ....... Manifold.CurveCircle // ....... Manifold.Curve
The above example composes a geom value and reports the curves.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveCircle(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 0)); builder.AddCoord(new Manifold.Point<double>(3, 1)); builder.AddCoord(new Manifold.Point<double>(4, 0)); builder.AddCurveCircle(new Manifold.Point<double>(5, 1)); builder.AddCoord(new Manifold.Point<double>(6, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); Manifold.Geom.CurveSet curves = geom.Curves; for (int index = 0; index < curves.Count; ++index) { Manifold.Curve curve = curves[index]; if (curve.Type == "") continue; // straight line segment app.Log(string.Format("Curve between {0} and {1}", index, index + 1)); } app.OpenLog(); } // result: Curve between 0 and 1 // ....... Curve between 3 and 4
The above example composes a geom value and reports indexes of coordinates connected with curves.
18.5. Geom.GetBytes
Syntax
byte[] GetBytes()
Return Value
Returns the binary representation of the geom value.
Notes
Each call to the method returns a new object.
To convert the binary representation back to a geom value, use TypeConverter.Convert.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 2)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); // get bytes byte[] bytes = geom.GetBytes(); // convert back to geom geom = (Manifold.Geom)converter.Convert(bytes, typeof(Manifold.Geom)); Manifold.Geom.CoordSet coords = geom.Coords; for (int index = 0; index < coords.Count; ++index) app.Log(coords[index].ToString()); } app.OpenLog(); } // result: [ 1, 1 ] // ....... [ 2, 2 ]
The above example composes a geom value, gets it binary representation, converts the binary representation back to a geom value and reports the coordinates.
18.6. Geom.HasCurves
Syntax
bool HasCurves
Return Value
Returns true if the geom value contains curves, otherwise returns false.
Notes
Curves can appear in area or line geom values.
Curves are either 2d or 3d. In a 2d geom value, all curves are 2d. In a 3d geom value, all curves are 3d.
To replace curves in a geom value with straight line approximations, use an Expression object with an appropriate query expression.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveCircle(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.HasCurves.ToString()); app.OpenLog(); } // result: True
The above example composes a geom value and checks if it contains curves.
18.7. Geom.HasZ
Syntax
bool HasZ
Return Value
Returns true if the geom value is 3d, otherwise returns false.
Notes
Geom values of all types can be 2d or 3d.
In a 3d area geom value, the first coordinate of each branch coincides with the last coordinate of the same branch including the Z value.
To convert a geom value from 2d to 3d or vice versa, either use a GeomBuilder object to compose a new geom value from the coordinates of the existing geom value, or use an Expression object with an appropriate query expression.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomPoint3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(1, 1, 1)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.HasZ.ToString()); app.OpenLog(); } // result: True
The above example composes a geom value and checks if it is 3d.
18.8. Geom.IsArea
Syntax
bool IsArea
Return Value
Returns true if the geom value is an area, otherwise returns false.
Notes
An area geom value can have multiple coordinates and multiple branches. The first coordinate of each branch coincides with the last coordinate of the same branch. Area segments can be curves.
An area geom value can be either 2d or 3d.
To get the type of a geom value, use Geom.Type.
18.9. Geom.IsLine
Syntax
bool IsLine
Return Value
Returns true if the geom value is a line, otherwise returns false.
Notes
A line geom value can have multiple coordinates and multiple branches. Line segments can be curves.
A line geom value can be either 2d or 3d.
To get the type of a geom value, use Geom.Type.
18.10. Geom.IsPoint
Syntax
bool IsPoint
Return Value
Returns true if the geom value is a point, otherwise returns false.
Notes
A point geom value can have multiple coordinates and multiple branches.
A point geom value can be either 2d or 3d.
To get the type of a geom value, use Geom.Type.
18.11. Geom.Opts
Syntax
int Opts
Return Value
Returns option flags for the geom value.
Notes
Option flags contain type of the geom value and various indicators.
To get the type of a geom value, use Geom.Type. To check if a geom value is an area, line or point, use Geom.IsArea, Geom.IsLine or Geom.IsPoint. To check if a geom value contains curves, use Geom.HasCurves. To check if a geom value is 3d, use Geom.HasZ.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomPoint3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(1, 1, 1)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Opts.ToString()); app.OpenLog(); } // result: 33
The above example composes a geom value and reports its option flags.
18.12. Geom.Type
Syntax
string Type
Return Value
Returns the type of the geom value.
Notes
Geom values can be areas, lines or points.
To change the type of a geom value, either use a GeomBuilder object to compose a new geom value from the coordinates of the existing geom value, or use an Expression object with an appropriate query expression.
To check if a geom value is an area, line or point, use Geom.IsArea, Geom.IsLine or Geom.IsPoint.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomPoint3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(1, 1, 1)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Type); app.OpenLog(); } // result: point
The above example composes a geom value and reports its type.
19. Geom.Branch
19.1. Geom.Branch.Begin
Syntax
int Begin
Return Value
Returns the index of the first branch coordinate in the geom value.
19.2. Geom.Branch.Coords
Syntax
Geom.CoordSet Coords
COM languages:
Geom.CoordSet CoordObjs
Return Value
Returns 2d coordinates of the branch.
Notes
In an area geom value, the first coordinate of each branch coincides with the last coordinate.
The 2d coordinates are available for both 2d and 3d geom values. To access the 3d coordinates of the branch of a 3d geom value, use Branch.Coord3s.
To access the 2d coordinates of the entire geom value, use Geom.Coords.
19.3. Geom.Branch.Coord3s
Syntax
Geom.Coord3Set Coord3s
COM languages:
Geom.Coord3Set Coord3Objs
Return Value
Returns 3d coordinates of the branch. Returns a null reference if the geom value is 2d.
Notes
In an area geom value, the first coordinate of each branch coincides with the last coordinate.
To access the 3d coordinates of the entire geom value, use Geom.Coord3s.
19.4. Geom.Branch.Curves
Syntax
Geom.CurveSet Curves
Return Value
Returns the curves of the branch. Returns a null reference if the geom value contains no curves.
Notes
The last curve of each branch is ignored in computations and is set to a straight line segment.
To access the curves of the entire geom value, use Geom.Curves.
19.5. Geom.Branch.End
Syntax
int End
Return Value
Returns the index of the coordinate after the last branch coordinate in the geom value.
Notes
The returned index is one larger than the index of the last valid coordinate of the branch and should not be used to retrieve branch coordinates without adjustment.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 1)); builder.EndBranch(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 3)); builder.AddCoord(new Manifold.Point<double>(2, 3)); builder.AddCoord(new Manifold.Point<double>(3, 4)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); Manifold.Geom.Branch branch = geom.Branches[geom.Branches.Count - 1]; // last Manifold.Geom.CoordSet coords = geom.Coords; for (int index = branch.Begin; index < branch.End; ++index) app.Log(coords[index].ToString()); app.OpenLog(); } // result: [ 1, 3 ] // ....... [ 2, 3 ] // ....... [ 3, 4 ]
The above example composes a geom value and reports the coordinates in the last branch.
20. Geom.BranchSet
20.1. Geom.BranchSet indexers
Syntax
Geom.Branch object[int index]
Parameters
index - index of branch.
Return Value
Returns the branch with the specified index.
20.2. Geom.BranchSet.Count
Syntax
int Count
Return Value
Returns the number of branches.
21. Geom.CoordSet
21.1. Geom.CoordSet indexers
Syntax
Point<double> object[int index]
Parameters
index - index of coordinate.
Return Value
Returns the coordinate with the specified index.
21.2. Geom.CoordSet.Count
Syntax
int Count
Return Value
Returns the number of coordinates.
22. Geom.Coord3Set
22.1. Geom.Coord3Set indexers
Syntax
Point3<double> object[int index]
Parameters
index - index of coordinate.
Return Value
Returns the coordinate with the specified index.
22.2. Geom.Coord3Set.Count
Syntax
int Count
Return Value
Returns the number of coordinates.
23. Geom.CurveSet
23.1. Geom.CurveSet indexers
Syntax
Curve object[int index]
Parameters
index - index of curve.
Return Value
Returns the curve with the specified index.
23.2. Geom.CurveSet.Count
Syntax
int Count
Return Value
Returns the number of curves.
24. GeomBuilder
24.1. GeomBuilder.AddBranch
Syntax
void AddBranch()
Notes
The method adds a new branch to the current geom value.
If the geom builder contains an incomplete branch, all data for that branch is removed.
If the geom builder does not contain a geom value, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve from the current coordinate to the next coordinate, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3. To finish the current branch, use GeomBuilder.EndBranch.
Examples
// copy geom, place each segment into separate branch static Manifold.Geom MakeSegments(Manifold.GeomBuilder builder, Manifold.Geom geom) { builder.StartGeomLine(); for (int index = 0; index < geom.Branches.Count; ++index) { Manifold.Geom.CoordSet coords = geom.Branches[index].Coords; for (int coord = 0; coord < coords.Count - 1; ++coord) { builder.AddBranch(); builder.AddCoord(coords[coord]); builder.AddCoord(coords[coord + 1]); builder.EndBranch(); } } return builder.EndGeom(); } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; // build line Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 2)); builder.AddCoord(new Manifold.Point<double>(1, 3)); builder.AddCoord(new Manifold.Point<double>(1, 4)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); // convert to segments geom = MakeSegments(builder, geom); Manifold.Geom.BranchSet branches = geom.Branches; Manifold.Geom.CoordSet coords = geom.Coords; for (int index = 0; index < branches.Count; ++index) { Manifold.Geom.Branch branch = branches[index]; app.Log(string.Format("{0} : {1}", coords[branch.Begin], coords[branch.End - 1])); } app.OpenLog(); } // result: [ 1, 2 ] : [ 1, 3 ] // ....... [ 1, 3 ] : [ 1, 4 ]
The above example composes a line geom value, splits it into segments and reports the coordinates.
24.2. GeomBuilder.AddCoord
Syntax
void AddCoord(Point<double> coord)
Parameters
coord - new coordinate.
Notes
The method adds a new coordinate to the current geom value.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the current geom value is 3d, the method will fail.
To add a new coordinate to the current branch of a 3d geom value, use GeomBuilder.AddCoord3. To add a new curve from the current coordinate to the next coordinate, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); for (int index = 0; index < 10; ++index) builder.AddCoord(new Manifold.Point<double>(index, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Coords.Count.ToString()); app.OpenLog(); } // result: 10
The above example composes a 2d geom value and reports the number of coordinates.
24.3. GeomBuilder.AddCoord3
Syntax
void AddCoord3(Point3<double> coord)
Parameters
coord - new coordinate.
Notes
The method adds a new coordinate to the current geom value.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the current geom value is 2d, the method will fail.
To add a new coordinate to the current branch of a 2d geom value, use GeomBuilder.AddCoord. To add a new curve from the current coordinate to the next coordinate, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine3(); builder.AddBranch(); for (int index = 0; index < 10; ++index) builder.AddCoord3(new Manifold.Point3<double>(index, 0, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Coords.Count.ToString()); app.OpenLog(); } // result: 10
The above example composes a 3d geom value and reports the number of coordinates.
24.4. GeomBuilder.AddCurveCircle
Syntax
void AddCurveCircle(Point<double> coord)
Parameters
coord - the coordinate on the circular arc.
Notes
The method adds a new curve to the current geom value. The curve connects the current coordinate with the next coordinate.
The curve is a circular arc. The circle is defined by the starting and ending coordinates and the additional coordinate specified by the coord parameter. The arc passes through the additional coordinate specified by the coord parameter.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder already contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current geom value is a point, the method will fail.
If the current geom value is 3d, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve of a different type, use GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveCircle(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Curves[0].ToString()); app.OpenLog(); } // result: Manifold.CurveCircle
The above example composes a geom value with a circular arc and verifies the type of the created curve.
24.5. GeomBuilder.AddCurveCircle3
Syntax
void AddCurveCircle3(Point3<double> coord)
Parameters
coord - the coordinate on the 3d circular arc.
Notes
The method adds a new curve to the current geom value. The curve connects the current coordinate with the next coordinate.
The curve is a 3d circular arc. The 3d circle is defined by the starting and ending coordinates and the additional coordinate specified by the coord parameter. The arc passes through the additional coordinate specified by the coord parameter.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder already contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current geom value is a point, the method will fail.
If the current geom value is 2d, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve of a different type, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(0, 0, 0)); builder.AddCurveCircle3(new Manifold.Point3<double>(1, 1, 0)); builder.AddCoord3(new Manifold.Point3<double>(2, 0, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Curves[0].ToString()); app.OpenLog(); } // result: Manifold.CurveCircle3
The above example composes a 3d geom value with a circular arc and verifies the type of the created curve.
24.6. GeomBuilder.AddCurveEllipse
Syntax
void AddCurveEllipse(Point<double> coord, Point<double> center, double axis, double axisRotation)
Parameters
coord - the coordinate on the ellipsoidal arc.
center - the center of the ellipse.
axis - the major axis of the ellipse.
axisRotation - the rotation angle of the major axis of the ellipse in radians.
Notes
The method adds a new curve to the current geom value. The curve connects the current coordinate with the next coordinate.
The curve is an ellipsoidal arc. The ellipse is defined by the starting and ending coordinates as well as the center, axis and axisRotation parameters. The arc passes through the additional coordinate specified by the coord parameter.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder already contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current geom value is a point, the method will fail.
If the current geom value is 3d, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve of a different type, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveEllipse(new Manifold.Point<double>(1, 2), new Manifold.Point<double>(1, 0), 4, System.Math.PI / 2.0); builder.AddCoord(new Manifold.Point<double>(2, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Curves[0].ToString()); app.OpenLog(); } // result: Manifold.CurveEllipse
The above example composes a geom value with an ellipsoidal arc and verifies the type of the created curve.
24.7. GeomBuilder.AddCurveEllipse3
Syntax
void AddCurveEllipse3(Point3<double> coord, Point3<double> center, double axis, double axisRotation)
Parameters
coord - the coordinate on the 3d ellipsoidal arc.
center - the center of the 3d ellipse.
axis - the major axis of the 3d ellipse.
axisRotation - the rotation angle of the major axis of the 3d ellipse on the ellipse plane in radians.
Notes
The method adds a new curve to the current geom value. The curve connects the current coordinate with the next coordinate.
The curve is a 3d ellipsoidal arc. The 3d ellipse is defined by the starting and ending coordinates as well as the center, axis and axisRotation parameters. The arc passes through the additional coordinate specified by the coord parameter.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder already contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current geom value is a point, the method will fail.
If the current geom value is 2d, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve of a different type, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(0, 0, 0)); builder.AddCurveEllipse3(new Manifold.Point3<double>(1, 2, 0), new Manifold.Point3<double>(1, 0, 0), 4, System.Math.PI / 2.0); builder.AddCoord3(new Manifold.Point3<double>(2, 0, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Curves[0].ToString()); app.OpenLog(); } // result: Manifold.CurveEllipse3
The above example composes a 3d geom value with an ellipsoidal arc and verifies the type of the created curve.
24.8. GeomBuilder.AddCurveSpline
Syntax
void AddCurveSpline(int order, Point<double>[] coords, double[] weights, double[] knots)
Parameters
order - spline order, 2 or higher.
coords - intermediate control points.
weights - weights for the starting coordinate, intermediate control points and the ending coordinate.
knots - knots.
Notes
The method adds a new curve to the current geom value. The curve connects the current coordinate with the next coordinate.
The curve is a non-uniform rational B-spline of the specified order.
The coords parameter specifies intermediate control points that define the shape of the spline. The spline does not necessarily pass through the intermediate control points.
The weights parameter specifies weights for the starting coordinate, each of the intermediate control points and the ending coordinate of the spline.
The knots parameter specifies additional control values for the spline. The number of knots is equal to the number of spline coordinates (number of the intermediate control points + 2) + order + 1. The knots are in non-decreasing order.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder already contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current geom value is a point, the method will fail.
If the current geom value is 3d, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve of a different type, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3 or GeomBuilder.AddCurveSpline3.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCurveSpline(2, new Manifold.Point<double>[] { new Manifold.Point<double>(1, 2), new Manifold.Point<double>(2, 1), new Manifold.Point<double>(3, 2), }, new double[] { 1, 1, 1, 1, 1 }, new double[] { 0, 0, 0, 1, 2, 3, 3, 3 }); builder.AddCoord(new Manifold.Point<double>(4, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Curves[0].ToString()); app.OpenLog(); } // result: Manifold.CurveSpline
The above example composes a geom value with a spline and verifies the type of the created curve.
24.9. GeomBuilder.AddCurveSpline3
Syntax
void AddCurveSpline3(int order, Point3<double>[] coords, double[] weights, double[] knots)
Parameters
order - 3d spline order, 2 or higher.
coords - intermediate control points.
weights - weights for the starting coordinate, intermediate control points and the ending coordinate.
knots - knots.
Notes
The method adds a new curve to the current geom value. The curve connects the current coordinate with the next coordinate.
The curve is a 3d non-uniform rational B-spline of the specified order.
The coords parameter specifies intermediate control points that define the shape of the spline. The spline does not necessarily pass through the intermediate control points.
The weights parameter specifies weights for the starting coordinate, each of the intermediate control points and the ending coordinate of the spline.
The knots parameter specifies additional control values for the spline. The number of knots is equal to the number of spline coordinates (number of the intermediate control points + 2) + order + 1. The knots are in non-decreasing order.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder already contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current geom value is a point, the method will fail.
If the current geom value is 2d, the method will fail.
To add a new coordinate to the current branch, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve of a different type, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3 or GeomBuilder.AddCurveSpline.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine3(); builder.AddBranch(); builder.AddCoord3(new Manifold.Point3<double>(0, 0, 0)); builder.AddCurveSpline3(2, new Manifold.Point3<double>[] { new Manifold.Point3<double>(1, 2, 0), new Manifold.Point3<double>(2, 1, 0), new Manifold.Point3<double>(3, 2, 0), }, new double[] { 1, 1, 1, 1, 1 }, new double[] { 0, 0, 0, 1, 2, 3, 3, 3 }); builder.AddCoord3(new Manifold.Point3<double>(4, 0, 0)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(geom.Curves[0].ToString()); app.OpenLog(); } // result: Manifold.CurveSpline3
The above example composes a 3d geom value with a spline and verifies the type of the created curve.
24.10. GeomBuilder.EndBranch
Syntax
void EndBranch()
Notes
The method finishes the current branch and adds it to the current geom value.
If the geom builder does not contain a geom value, the method will fail.
If the geom builder does not contain a started branch, the method will fail.
If the geom builder contains a curve connecting the current coordinate with the next coordinate, the method will fail.
If the current branch contains less coordinates than is required for the geom value of the current type, the method adds as many copies of the last coordinate as needed to meet the requirement.
If the geom builder contains an area geom value and the first coordinate of the current branch does not coincide with the current coordinate, the method adds a copy of the first coordinate of the current branch.
To finish the current geom value, use GeomBuilder.EndGeom.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomArea(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(0, 0)); builder.AddCoord(new Manifold.Point<double>(1, 5)); builder.AddCoord(new Manifold.Point<double>(5, 1)); builder.EndBranch(); // adds start of branch builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(7, 7)); builder.EndBranch(); // adds last coordinate and then start of branch builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(11, 12)); builder.AddCoord(new Manifold.Point<double>(12, 12)); builder.AddCoord(new Manifold.Point<double>(12, 11)); builder.AddCoord(new Manifold.Point<double>(11, 11)); builder.AddCoord(new Manifold.Point<double>(11, 12)); builder.EndBranch(); // adds nothing, branch is complete Manifold.Geom geom = builder.EndGeom(); for (int index = 0; index < geom.Branches.Count; ++index) { Manifold.Geom.CoordSet coords = geom.Branches[index].Coords; for (int coord = 0; coord < coords.Count; ++coord) app.Log(string.Format("Branch {0}: {1}", index, coords[coord])); } app.OpenLog(); } // result: Branch 0: [ 0, 0 ] // ....... Branch 0: [ 1, 5 ] // ....... Branch 0: [ 5, 1 ] // ....... Branch 0: [ 0, 0 ] // ....... Branch 1: [ 7, 7 ] // ....... Branch 1: [ 7, 7 ] // ....... Branch 1: [ 7, 7 ] // ....... Branch 2: [ 11, 12 ] // ....... Branch 2: [ 12, 12 ] // ....... Branch 2: [ 12, 11 ] // ....... Branch 2: [ 11, 11 ] // ....... Branch 2: [ 11, 12 ]
The above example composes an area geom value autocompleting branches and reports coordinates for each branch.
24.11. GeomBuilder.EndGeom
Syntax
Geom EndGeom()
Return Value
Returns the composed geom value.
Notes
The method finishes the current geom value and returns it. The geom builder is cleared.
If the geom builder contains an incomplete branch, all data for that branch is removed.
If the geom builder contains a geom value with no branches, the method returns a null reference.
If the geom builder does not contain a geom value, the method returns a null reference.
To finish the current branch prior to finishing the current geom value, use GeomBuilder.EndBranch.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 2)); builder.AddCoord(new Manifold.Point<double>(1, 3)); Manifold.Geom geom = builder.EndGeom(); // cancels current branch app.Log(geom == null? "<NULL>": geom.Type); app.OpenLog(); } // result: <NULL>
The above example starts composing a geom value, then abruptly finishes it and reports the result.
24.12. GeomBuilder.StartGeom
Syntax
void StartGeom(string type, bool z)
Parameters
type - type of the new geom value.
z - true if the new geom value is 3d, false if the new geom value is 2d.
Notes
The methods starts building a new geom value of the specified type.
If the geom builder contains an incomplete geom value, all data for that value is removed.
To add a new branch to a geom value, use GeomBuilder.AddBranch. To add a new coordinate, use GeomBuilder.AddCoord or GeomBuilder.AddCoord3. To add a new curve, use GeomBuilder.AddCurveCircle, GeomBuilder.AddCurveCircle3, GeomBuilder.AddCurveEllipse, GeomBuilder.AddCurveEllipse3, GeomBuilder.AddCurveSpline or GeomBuilder.AddCurveSpline3. To finish the current branch, use GeomBuilder.EndBranch. To finish the current geom value, use GeomBuilder.EndGeom.
Examples
// copy geom, add Z values static Manifold.Geom AddZ(Manifold.GeomBuilder builder, Manifold.Geom geom, double z) { builder.StartGeom(geom.Type, true); for (int index = 0; index < geom.Branches.Count; ++index) { builder.AddBranch(); Manifold.Geom.CoordSet coords = geom.Branches[index].Coords; for (int coord = 0; coord < coords.Count; ++coord) builder.AddCoord3(new Manifold.Point3<double>(coords[coord].X, coords[coord].Y, z)); builder.EndBranch(); } return builder.EndGeom(); } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; // build 2d line Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 2)); builder.AddCoord(new Manifold.Point<double>(1, 3)); builder.AddCoord(new Manifold.Point<double>(1, 4)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); // convert to 3d line geom = AddZ(builder, geom, 10); Manifold.Geom.Coord3Set coords = geom.Coord3s; for (int index = 0; index < coords.Count; ++index) app.Log(coords[index].ToString()); app.OpenLog(); } // result: [ 1, 2, 10 ] // ....... [ 1, 3, 10 ] // ....... [ 1, 4, 10 ]
The above example composes a 3d geom value, converts it to a 3d geom value and reports the coordinates.
24.13. GeomBuilder.StartGeomArea
Syntax
void StartGeomArea()
Notes
The method starts building a new 2d area geom value.
If the geom builder contains an incomplete geom value, all data for that value is removed.
24.14. GeomBuilder.StartGeomArea3
Syntax
void StartGeomArea3()
Notes
The method starts building a new 3d area geom value.
If the geom builder contains an incomplete geom value, all data for that value is removed.
24.15. GeomBuilder.StartGeomLine
Syntax
void StartGeomLine()
Notes
The method starts building a new 2d line geom value.
If the geom builder contains an incomplete geom value, all data for that value is removed.
24.16. GeomBuilder.StartGeomLine3
Syntax
void StartGeomLine3()
Notes
The method starts building a new 3d line geom value.
If the geom builder contains an incomplete geom value, all data for that value is removed.
24.17. GeomBuilder.StartGeomPoint
Syntax
void StartGeomPoint()
Notes
The method starts building a new 2d point geom value.
If the geom builder contains an incomplete geom value, all data for that value is removed.
24.18. GeomBuilder.StartGeomPoint3
Syntax
void StartGeomPoint3()
Notes
The method starts building a new 3d point geom value.
If the geom builder contains an incomplete geom value, all data for that value is removed.
25. GeomWkb
25.1. GeomWkb.GetBytes
Syntax
byte[] GetBytes()
Return Value
Returns the binary representation of the geom WKB value.
Notes
Each call to the method returns a new object.
To convert the binary representation back to a geom WKB value, use TypeConverter.Convert.
To access the coordinates of a geom WKB value, convert it to a geom value using TypeConverter.Convert.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 2)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); app.Log(string.Format("Geom: {0} bytes", geom.GetBytes().Length)); Manifold.GeomWkb geomWkb = (Manifold.GeomWkb)converter.Convert(geom, typeof(Manifold.GeomWkb)); app.Log(string.Format("GeomWkb: {0} bytes", geomWkb.GetBytes().Length)); } app.OpenLog(); } // result: Geom: 44 bytes // ....... GeomWkb: 41 bytes
The above example composes a geom value, converts it to a geom WKB value and reports the number of bytes in the binary representation of each.
26. Point
26.1. Point constructor
Syntax
Point() Point(T x, T y)
Parameters
x - 1st coordinate.
y - 2nd coordinate.
Notes
Calling the constructor without parameters sets all coordinates to 0.
Point objects can also be created using Application.CreatePoint.
To access the coordinates of an existing object, use Point.X and Point.Y.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Point<int> p = new Manifold.Point<int>(); p.X = 1; p.Y = 2; app.Log(p.ToString()); app.OpenLog(); } // result: [ 1, 2 ]
The above example creates a new point and sets its coordinates.
26.2. Point.X
Syntax
T X
Return Value
Sets or returns the value of the 1st coordinate.
26.3. Point.Y
Syntax
T Y
Return Value
Sets or returns the value of the 2nd coordinate.
27. Point3
27.1. Point3 constructor
Syntax
Point3() Point3(T x, T y, T z)
Parameters
x - 1st coordinate.
y - 2nd coordinate.
z - 3rd coordinate.
Notes
Calling the constructor without parameters sets all coordinates to 0.
Point objects can also be created using Application.CreatePoint3.
To access the coordinates of an existing object, use Point3.X, Point3.Y and Point3.Z.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Point3<int> p = new Manifold.Point3<int>(); p.X = 1; p.Y = 2; p.Z = 3; app.Log(p.ToString()); app.OpenLog(); } // result: [ 1, 2, 3 ]
The above example creates a new point and sets its coordinates.
27.2. Point3.X
Syntax
T X
Return Value
Sets or returns the value of the 1st coordinate.
27.3. Point3.Y
Syntax
T Y
Return Value
Sets or returns the value of the 2nd coordinate.
27.4. Point3.Z
Syntax
T Z
Return Value
Sets or returns the value of the 3rd coordinate.
28. Point4
28.1. Point4 constructor
Syntax
Point4() Point4(T x, T y, T z, T w)
Parameters
x - 1st coordinate.
y - 2nd coordinate.
z - 3rd coordinate.
w - 4th coordinate.
Notes
Calling the constructor without parameters sets all coordinates to 0.
Point objects can also be created using Application.CreatePoint4.
To access the coordinates of an existing object, use Point4.X, Point4.Y, Point4.Z and Point4.W.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Point4<int> p = new Manifold.Point4<int>(1, 1, 1, 1); ++p.W; app.Log(p.ToString()); app.OpenLog(); } // result: [ 1, 1, 1, 2 ]
The above example creates a new point initializing all coordinates to 1, then alters the value of a coordinate.
28.2. Point4.W
Syntax
T W
Return Value
Sets or returns the value of the 4th coordinate.
28.3. Point4.X
Syntax
T X
Return Value
Sets or returns the value of the 1st coordinate.
28.4. Point4.Y
Syntax
T Y
Return Value
Sets or returns the value of the 2nd coordinate.
28.5. Point4.Z
Syntax
T Z
Return Value
Sets or returns the value of the 3rd coordinate.
29. Property
29.1. Property.Data
Syntax
string Data
Return Value
Returns property value.
29.2. Property.Name
Syntax
string Name
Return Value
Returns property name.
30. PropertySet
30.1. PropertySet indexers
Syntax
Property object[int index] Property object[string name]
Parameters
index - index of property.
name - name of property. Case-insensitive.
Return Value
Returns the property with the specified index or name.
Notes
If the property is searched by name and there is no property with the specified name, the method returns a null reference.
To get the value of the property that may or may not exist, use PropertySet.GetProperty.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Date", "1-Jan-2017"); properties.SetProperty("Description", "Example description"); for (int index = 0; index < properties.Count; ++index) { Manifold.Property prop = properties[index]; app.Log(string.Format("{0} : {1}", prop.Name, prop.Data)); } app.OpenLog(); } // result: Date : 1-Jan-2017 // ....... Description : Example description
The above example creates a property set, fills it with example values and reports all properties.
30.2. PropertySet.Clear
Syntax
void Clear()
Notes
Deletes all properties.
To delete a specific property, use PropertySet.DeleteProperty. To add a new property or set the value of an existing property, use PropertySet.SetProperty. To get the value of a property, use PropertySet.GetProperty.
30.3. PropertySet.Count
Syntax
int Count
Return Value
Returns the number of properties.
30.4. PropertySet.DeleteProperty
Syntax
void DeleteProperty(string name)
Parameters
name - name of the property to delete. Case-insensitive.
Notes
The method attempts to delete the property with the specified name.
Attempting to delete the property that does not exist has no effect.
To delete all properties, use PropertySet.Clear. To add a new property or set the value of an existing property, use PropertySet.SetProperty. To get the value of a property, use PropertySet.GetProperty.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Date", "1-Jan-2017"); properties.SetProperty("Description", "Example description"); properties.DeleteProperty("Abstract"); properties.DeleteProperty("Description"); for (int index = 0; index < properties.Count; ++index) { Manifold.Property prop = properties[index]; app.Log(string.Format("{0} : {1}", prop.Name, prop.Data)); } app.OpenLog(); } // result: Date : 1-Jan-2017
The above example creates a property set, fills it with example values, then attempts to delete several properties and reports the final properties.
30.5. PropertySet.GetProperty
Syntax
string GetProperty(string name)
Parameters
name - name of the property to locate. Case-insensitive.
Return Value
Returns the value of the property with the specified name. Returns an empty string if the property does not exist.
Notes
To determine if the property exists, use PropertySet indexers. To delete a property, use PropertySet.DeleteProperty. To delete all properties, use PropertySet.Clear. To add a new property or set the value of an existing property, use PropertySet.SetProperty.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Date", "1-Jan-2017"); properties.SetProperty("Description", "Example description"); app.Log(string.Format("Abstract : {0}", properties.GetProperty("Abstract"))); app.Log(string.Format("Date : {0}", properties.GetProperty("Date"))); app.OpenLog(); } // result: Abstract : // ....... Date : 1-Jan-2017
The above example creates a property set, fills it with example values, then requests the values of several properties and reports the result.
30.6. PropertySet.SetProperty
Syntax
void SetProperty(string name, bool value) void SetProperty(string name, double value) void SetProperty(string name, string value) void SetProperty(string name, Point<T> value) void SetProperty(string name, Point3<T> value) void SetProperty(string name, Point4<T> value) void SetProperty(string name, PropertySet value)
Parameters
name - name of the property to add or change. Case-insensitive.
value - value of the property. Can be a boolean value, a numeric value, a string value, a point value or a property set object.
NOtes
The method adds a new property with the specified name and value. If the property with the specified name does not exist, a new property is added.
The value is converted to a string value according to JSON rules. A boolean value is converted to a JSON literal. A numeric value is converted to a JSON number. A point value is converted to a JSON vector. A property set value is converted to a JSON object. A string value is left unchanged.
To delete a property, use PropertySet.DeleteProperty. To delete all properties, use PropertySet.Clear. To get the value of a property, use PropertySet.GetProperty.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Date", "1-Jan-2017"); properties.SetProperty("Approved", true); properties.SetProperty("Rate", 74.5); app.Log(properties.ToJson()); app.OpenLog(); } // result: { "Approved": true, "Date": "1-Jan-2017", "Rate": 74.5 }
The above example creates a property set, fills it with example values and reports the result as JSON.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet propertiesRates = app.CreatePropertySet(); propertiesRates.SetProperty("Day", 74.5); propertiesRates.SetProperty("Night", 99.5); Manifold.PropertySet properties = app.CreatePropertySet(); properties.SetProperty("Date", "1-Jan-2017"); properties.SetProperty("Approved", true); properties.SetProperty("Rates", propertiesRates); app.Log(properties.ToJson()); app.OpenLog(); } // result: { "Approved": true, "Date": "1-Jan-2017", "Rates": { "Day": 74.5, "Night": 99.5 } }
The above example creates a property set, fills it with example values, then inserts it into another property set as a value and reports the result as JSON.
30.7. PropertySet.ToJson
Syntax
string ToJson()
Return Value
Returns the property set as a JSON string.
Notes
To parse the JSON string back to a property set, use Application.CreatePropertySetParse.
Examples
See examples for PropertySet.SetProperty.
31. Root
31.1. Root constructor
Syntax
Root(string path)
Parameters
path - path to EXT.DLL. May be empty.
Notes
Creating an instance of the object attempts to start and initialize the object model.
If path is a non-empty string, the object will attempt to use EXT.DLL in the specified location. If path is an empty string, the object will try to use EXT.DLL in the default installation path:
C:\Program Files\Manifold\v9.0\Bin, if the application attempting to create an instance of the object is 32-bit,
C:\Program Files\Manifold\v9.0\Bin64, if the application attempting to create an instance of the object is 64-bit.
If the object model fails to initialize, attempting to create an instance of the object will throw an exception.
31.2. Root.Application
Syntax
Application Application
Return Value
Returns the application object for the initialized object model.
32. Schema
32.1. Schema.AddConstraint
Syntax
void AddConstraint(string name, string expression) void AddConstraint(string name, string expression, string expressionContext)
Parameters
name - name of the constraint to add. Case-insensitive.
expression - expression for the constraint.
expressionContext - expression context for the constraint.
Notes
The method adds a new constraint with the specified name, expression and expression context. If the specified name is already used by an existing constraint, field or index, the method will fail.
The expression can not be empty.
The expression can use values and functions defined in the expression context.
The values and functions defined in the expression context are computed when the table is loaded.
The expression in a constraint can be unsatisfiable. Adding such a constraint to a table with no records will succeed, but attempting to add records after that will fail.
The expressions in a set of constraints can be satisfiable individually but unsatisfiable as a whole. Adding such a set of constraints to a table with no records will succeed, but attempting to add records after that will fail.
To delete a constraint, use Schema.DeleteConstraint. To access all constraints, use Schema.Constraints.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "int32"); schema.AddConstraint("a_c", "a > b"); schema.AddConstraint("b_c", "a < b"); // inserting records is impossible foreach (Manifold.Schema.Constraint constraint in schema.Constraints) app.Log(string.Format("{0} : {1}", constraint.Name, constraint.Expression)); app.OpenLog(); } // result: a_c : a > b // ....... b_c : a < b
The above example creates a new schema, adds a pair of constraints that are unsatisfiable as a whole and reports the results.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("x", "float64"); schema.AddField("y", "float64"); schema.AddConstraint("x_y_c", "Sqrt(x*x + y*y) < @rad", "VALUE @rad FLOAT64 = 100;"); foreach (Manifold.Schema.Constraint constraint in schema.Constraints) app.Log(string.Format("{0} : {1} : {2}", constraint.Name, constraint.Expression, constraint.ExpressionContext)); app.OpenLog(); } // result: x_y_c : Sqrt(x*x + y*y) < @rad : VALUE @rad FLOAT64 = 100;
The above example creates a new schema, adds a constraint with an expression that uses a value defined in an expression context and reports the results.
32.2. Schema.AddField
Syntax
void AddField(string name, string type) void AddField(string name, System.Type type)
Parameters
name - name of the field to add. Case-insensitive.
type - type of the field. Can be either a .NET type object or a string with the name of the Manifold type.
Notes
The method adds a new field with the specified name and type. If the specified name is already used by an existing constraint, field or index, the method will fail.
To add a computed field, use Schema.AddFieldComputed. To delete a field, use Schema.DeleteField. To access all fields, use Schema.Fields.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", typeof(int)); schema.AddField("b", typeof(string)); schema.AddField("c", typeof(Manifold.Geom)); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(string.Format("{0} : {1}", field.Name, field.Type)); app.OpenLog(); } // result: a : int32 // ....... b : nvarchar // ....... c : geom
The above example creates a new schema, adds several fields specifying their types as .NET type objects and reports the results.
32.3. Schema.AddFieldComputed
Syntax
void AddFieldComputed(string name, string type, string expression) void AddFieldComputed(string name, string type, string expression, string expressionContext) void AddFieldComputed(string name, System.Type type, string expression) void AddFieldComputed(string name, System.Type type, string expression, string expressionContext)
Parameters
name - name of the field to add. Case-insensitive.
type - type of the field. Can be either a .NET type object or a string with the name of the Manifold type.
expression - expression for the computed field.
expressionContext - expression context for the computed field.
Notes
The method adds a new computed field with the specified name, type, expression and expression context. If the specified name is already used by an existing constraint, field or index, the method will fail.
The expression can use values and functions defined in the expression context.
The values and functions defined in the expression context are computed when the table is loaded.
The values of a computed field are computed automatically when the values of the fields used by the expression are about to change and when a new record is about to be inserted. The values of a computed field are read-only.
To add a regular field, use Schema.AddField. To delete a field, use Schema.DeleteField. To access all fields, use Schema.Fields.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddFieldComputed("b", "int32", "a + 100"); schema.AddField("c", "int32"); schema.Fields["c"].Expression = "b + 200"; // makes field computed foreach (Manifold.Schema.Field field in schema.Fields) app.Log(string.Format("{0} : {1}", field.Name, field.Expression)); app.OpenLog(); } // result: a : // ....... b : a + 100 // ....... c : b + 200
The above example creates a new schema, adds several regular and computed fields and reports the results.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("lat", "float64"); schema.AddField("lon", "float64"); schema.AddFieldComputed("convertedxy", "float64x2", "CoordConvertPoint(@conv, VectorMakeX2(lat, lon))", // lat first "VALUE @conv TABLE = CALL CoordConverterMake('EPSG:3857', 'EPSG:4326');"); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(string.Format("{0} : {1} : {2}", field.Name, field.Expression, field.ExpressionContext)); app.OpenLog(); } // result: lat : : // ....... lon : : // ....... convertedxy : CoordConvertPoint(@conv, VectorMakeX2(lat, lon)) // : VALUE @conv TABLE = CALL CoordConverterMake('EPSG:3857', 'EPSG:4326');
The above example creates a new schema, adds regular fields, adds a computed field with an expression that uses a value defined in an expression context and reports the results.
32.4. Schema.AddIndex
Syntax
void AddIndex(string name, string type) void AddIndex(string name, string type, string[] fields)
Parameters
name - name of the index to add. Case-insensitive.
type - type of the index.
fields - fields for the index.
Notes
The method adds a new index with the specified name, type and fields. If the specified name is already used by an existing constraint, field or index, the method will fail.
Supported index types are:
-
"btree" - a btree index on one or more fields, disallows duplicates and NULL values,
-
"btreedup" - a btree index on one or more fields, allows duplicates, disallows NULL values,
-
"btreedupnull" - a btree index on one or more fields, allows duplicates and NULL values,
-
"btreenull" - a btree index on one or more fields, disallows duplicates, allows NULL values,
-
"rtree" - an rtree index on one or more fields with either vector or raster data.
An rtree index supports the following combinations of fields:
-
a single geom field (GEOM, GEOMMFD, GEOMWKB),
-
two numeric fields for X and Y (or Y and X) and a single tile field,
-
three numeric fields for level, X and Y (or level, Y and X) and a single tile field.
Indexes are used for fast searches and for data validation.
To delete an index, use Schema.DeleteIndex. To access all indexes, use Schema.Indexes.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("x", "int32"); schema.AddField("y", "int32"); schema.AddField("t", "tile"); schema.AddIndex("x_y_t_x", "rtree", new string[] { "x", "y", "t" }); Manifold.Schema.IndexField indexField = schema.Indexes[0].Fields[2]; // "t" indexField.TileSize = "[ 128, 128 ]"; indexField.TileType = "uint8x3"; foreach (Manifold.Schema.Index index in schema.Indexes) app.Log(string.Format("{0} : {1}", index.Name, index.Type)); app.OpenLog(); } // result: x_y_t_x : rtree
The above example creates a new schema, adds fields and an rtree index for raster data and reports the results.
See also examples for Table.SearchBatch.
32.5. Schema.Clear
Syntax
void Clear()
Notes
Deletes all constraints, fields and indexes.
To add a new constraint, use Schema.AddConstraint. To delete a specific constraint, use Schema.DeleteConstraint. To add a new field, use Schema.AddField or Schema.AddFieldComputed. To delete a specific field, use Schema.DeleteField. To add a new index, use Schema.AddIndex. To delete a specific index, use Schema.DeleteIndex.
32.6. Schema.Constraints
Syntax
Schema.ConstraintSet Constraints
Return Value
Returns schema constraints.
Notes
Constraints are boolean expressions required to evaluate to true for each record.
The order of constraints in the schema of a table might not follow the order the constraints have been added to the table. Reading the schema of a table may place the constraints in any order.
To add a new constraint, use Schema.AddConstraint. To delete a constraint, use Schema.DeleteConstraint. To access schema fields, use Schema.Fields. To access schema indexes, use Schema.Indexes.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddConstraint("a_c", "a > 0"); schema.AddConstraint("b_c", "b IS NOT NULL"); foreach (Manifold.Schema.Constraint constraint in schema.Constraints) app.Log(string.Format("{0} : {1}", constraint.Name, constraint.Expression)); app.OpenLog(); } // result: a_c : a > 0 // ....... b_c : b IS NOT NULL
The above example creates a new schema, adds several constraints and reports the results.
32.7. Schema.DeleteConstraint
Syntax
void DeleteConstraint(string name)
Parameters
name - name of the constraint to delete. Case-insensitive.
Notes
The method deletes the constraint with the specified name. If the constraint with the specified name does not exist, the method will fail.
To add a new constraint, use Schema.AddConstraint. To access constraints, use Schema.Constraints.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "int32"); schema.AddConstraint("a_c", "a > b"); schema.AddConstraint("b_c", "a < b"); schema.DeleteConstraint("b_c"); foreach (Manifold.Schema.Constraint constraint in schema.Constraints) app.Log(string.Format("{0} : {1}", constraint.Name, constraint.Expression)); app.OpenLog(); } // result: a_c : a > b
The above example creates a new schema, adds and deletes several constraints and reports the results.
32.8. Schema.DeleteField
Syntax
void DeleteField(string name)
Parameters
name - name of the field to delete. Case-insensitive.
Notes
The method deletes the field with the specified name. If the field with the specified name does not exist, the method will fail.
Deleting a field referenced by a computed field does not delete or alter the computed field. The computed field has to be deleted or altered manually.
Deleting a field referenced by an index does not delete or alter the index. The index has to be deleted or altered manually.
Deleting a field referenced by a constraint does not delete or alter the constraint. The constraint has to be deleted or altered manually.
To add a new field, use Schema.AddField or Schema.AddFieldComputed. To access fields, use Schema.Fields.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddField("c", "geom"); schema.DeleteField("a"); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(string.Format("{0} : {1}", field.Name, field.Type)); app.OpenLog(); } // result: b : nvarchar // ....... c : geom
The above example creates a new schema, adds and deletes several fields and reports the results.
32.9. Schema.DeleteIndex
Syntax
void DeleteIndex(string name)
Parameters
name - name of the index to delete. Case-insensitive.
Notes
The method deletes the index with the specified name. If the index with the specified name does not exist, the method will fail.
To add a new index, use Schema.AddIndex. To access indexes, use Schema.Indexes.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddField("c", "geom"); schema.AddIndex("a_x", "btree", new string[] { "a" }); schema.AddIndex("b_x", "btreedup", new string[] { "b" }); schema.AddIndex("a_b_x", "btreedup", new string[] { "a", "b" }); schema.DeleteIndex("b_x"); foreach (Manifold.Schema.Index index in schema.Indexes) app.Log(string.Format("{0} : {1}", index.Name, index.Type)); app.OpenLog(); } // result: a_x : btree // ....... a_b_x : btreedup
The above example creates a new schema, adds and deletes several indexes and reports the results.
32.10. Schema.Fields
Syntax
Schema.FieldSet Fields
Return Value
Returns schema fields.
Notes
The order of fields in the schema of a table might not follow the order the fields have been added to the table. Reading the schema of a table may place the fields in any order.
To add a new field, use Schema.AddField or Schema.AddFieldComputed. To delete a field, use Schema.DeleteField. To access schema constraints, use Schema.Constraints. To access schema indexes, use Schema.Indexes.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddField("c", "geom"); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(string.Format("{0} : {1}", field.Name, field.Type)); app.OpenLog(); } // result: a : int32 // ....... b : nvarchar // ....... c : geom
The above example creates a new schema, adds several fields and reports the results.
32.11. Schema.HasItem
Syntax
bool HasItem(string name)
Parameters
name - name of the constraint, field or index to locate. Case-insensitive.
Return Value
Returns true if the specified name corresponds to an existing constraint, field or index, otherwise returns false.
Notes
The method locates the constraint, field or index with the specified name.
To access constraints, use Schema.Constraints. To access fields, use Schema.Fields. To access indexes, use Schema.Indexes.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a1", "int32"); schema.AddField("a2", "nvarchar"); schema.AddField("a3", "geom"); schema.AddIndex("a4", "btree", new string[] { "a1" }); schema.AddConstraint("a5", "a1 > 0"); int counter = 1; while (true) { string name = string.Format("a{0}", counter++); if (schema.HasItem(name)) continue; app.Log("Unused name: " + name); break; } app.OpenLog(); } // result: Unused name: a6
The above example creates a new schema, fills it with example fields, indexes and constraints and determines the unique name for a new item.
32.12. Schema.Indexes
Syntax
Schema.IndexSet Indexes
Return Value
Returns schema indexes.
Notes
The order of indexes in the schema of a table might not follow the order the indexes have been added to the table. Reading the schema of a table may place the indexes in any order, although the fastest index is usually placed first.
To add a new index, use Schema.AddIndex. To delete an index, use Schema.DeleteIndex. To access schema constraints, use Schema.Constraints. To access schema fields, use Schema.Fields.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddField("c", "geom"); schema.AddIndex("a_x", "btree", new string[] { "a" }); schema.AddIndex("c_x", "rtree", new string[] { "c" }); foreach (Manifold.Schema.Index index in schema.Indexes) app.Log(string.Format("{0} : {1}", index.Name, index.Type)); app.OpenLog(); } // result: a_x : btree // ....... c_x : rtree
The above example creates a new schema, adds several indexes and reports the results.
33. Schema.Constraint
33.1. Schema.Constraint.Expression
Syntax
string Expression
Return Value
Sets or returns the expression for the constraint.
Notes
The expression of a constraint can use values or functions defined in the expression context.
To change the expression or expression context of an existing constraint in a table, remove the existing constraint and then add a new constraint.
33.2. Schema.Constraint.ExpressionContext
Syntax
string ExpressionContext
Return Value
Sets or returns the expression context for the constraint.
Notes
The expression context of a constraint defines values or functions for the expression.
To change the expression or expression context of an existing constraint in a table, remove the existing constraint and then add a new constraint.
33.3. Schema.Constraint.Name
Syntax
string Name
Return Value
Returns the name of the constraint.
34. Schema.ConstraintSet
34.1. Schema.ConstraintSet indexers
Syntax
Schema.Constraint object[int index] Schema.Constraint object[string name]
Parameters
index - index of the constraint.
name - name of the constraint. Case-insensitive.
Return Value
Returns the constraint with the specified index or name.
Notes
If the constraint is searched by name and there is no constraint with the specified name, the method returns a null reference.
34.2. Schema.ConstraintSet.Count
Syntax
int Count
Return Value
Returns the number of constraints.
35. Schema.Field
35.1. Schema.Field.Expression
Syntax
string Expression
Return Value
Sets or returns the expression for the computed field.
Notes
The expression of a computed field can use values or functions defined in the expression context.
To change the expression or expression context of an existing computed field in a table, remove the existing field and then add a new field.
To change an existing regular field in a table to a computed field, remove the existing field and then add a new field.
To change an existing computed field in a table to a regular field, add a new field, copy all data from the old field to the new field, remove the old field, then rename the new field to the name of the old field.
35.2. Schema.Field.ExpressionContext
Syntax
string ExpressionContext
Return Value
Sets or returns the expression context for the computed field.
Notes
The expression context of a computed field defines values or functions for the expression.
To change the expression or expression context of an existing computed field in a table, remove the existing field and then add a new field.
To change an existing regular field in a table to a computed field, remove the existing field and then add a new field.
To change an existing computed field in a table to a regular field, add a new field, copy all data from the old field to the new field, remove the old field, then rename the new field to the name of the old field.
35.3. Schema.Field.Name
Syntax
string Name
Return Value
Returns the name of the field.
35.4. Schema.Field.Type
Syntax
string Type
Return Value
Sets or returns the type of field values.
Notes
To access the .NET type used for field values, use Schema.Field.TypeClr.
To change the type of an existing field in a table, add a new field, copy all data from the old field to the new field, remove the old field, then rename the new field to the name of the old field.
35.5. Schema.Field.TypeClr
Syntax
System.Type TypeClr
Return Value
Sets or returns the type of field values as a .NET type object.
Notes
To access the name of the Manifold type used for field values, use Schema.Field.Type.
To change the type of an existing field in a table, add a new field, copy all data from the old field to the new field, remove the old field, then rename the new field to the name of the old field.
36. Schema.FieldSet
36.1. Schema.FieldSet indexers
Syntax
Schema.Field object[int index] Schema.Field object[string name]
Parameters
index - index of the field.
name - name of the field. Case-insensitive.
Return Value
Returns the field with the specified index or name.
Notes
If the field is searched by name and there is no field with the specified name, the method returns a null reference.
36.2. Schema.FieldSet.Count
Syntax
int Count
Return Value
Returns the number of fields.
37. Schema.Index
37.1. Schema.Index.AddField
Syntax
void AddField(string name)
Parameters
name - name of the index field to add. Case-insensitive.
Notes
The method adds a new index field with the specified name. If the index field with the specified name already exists, the method will fail.
To delete an index field, use Schema.Index.DeleteField. To check if the index field with the specified name exists, use Schema.Index.HasField.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddIndex("a_x", "btree"); Manifold.Schema.Index index = schema.Indexes[0]; // or ["a_x"] index.AddField("a"); foreach (Manifold.Schema.IndexField indexField in index.Fields) app.Log(indexField.Name); app.OpenLog(); } // result: a
The above example creates a new schema, adds a new index, adds a field to the new index and reports the final index fields.
37.2. Schema.Index.DeleteField
Syntax
void DeleteField(string name)
Parameters
name - name of the index field to delete. Case-insensitive.
Notes
The method deletes an index field with the specified name. If the index field with the specified name does not exist, the method will fail.
To add a new index field, use Schema.Index.AddField. To check if the index field with the specified name exists, use Schema.Index.HasField.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddIndex("a_x", "btree"); Manifold.Schema.Index index = schema.Indexes[0]; // or ["a_x"] index.AddField("a"); index.AddField("b"); index.DeleteField("b"); foreach (Manifold.Schema.IndexField indexField in index.Fields) app.Log(indexField.Name); app.OpenLog(); } // result: a
The above example creates a new schema, adds a new index, adds and deletes fields in the new index and reports the final index fields.
37.3. Schema.Index.Fields
Syntax
Schema.IndexFieldSet Fields
Return Value
Returns the index fields.
Notes
The order of index fields defines the index structure. The index fields always appear in the order used by the index.
To change the fields of an existing index in a table or to change the order they are used by the index, remove the existing index and then add a new index.
To add a new index field, use Schema.Index.AddField. To delete an index field, use Schema.Index.DeleteField. To check if the index field with the specified name exists, use Schema.Index.HasField.
37.4. Schema.Index.HasField
Syntax
bool HasField(string name)
Parameters
name - name of the index field to locate. Case-insensitive.
Return Value
Returns true if the index field with the specified name exists, otherwise returns false.
Notes
The method locates an index field with the specified name.
To add a new index field, use Schema.Index.AddField. To delete an index field, use Schema.Index.DeleteField.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); schema.AddIndex("a_x", "btree"); Manifold.Schema.Index index = schema.Indexes[0]; // or ["a_x"] index.AddField("a"); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(field.Name + (index.HasField(field.Name)? " : in index": " : not in index")); app.OpenLog(); } // result: a : in index // ....... b : not in index
The above example creates a new schema, adds a new index with some fields and reports for each field if it is in the index.
37.5. Schema.Index.Name
Syntax
string Name
Return Value
Returns the name of the index.
37.6. Schema.Index.Type
Syntax
string Type
Return Value
Sets or returns the type of the index.
Notes
To change the type of an existing index in a table, remove the existing index and then add a new index.
38. Schema.IndexField
38.1. Schema.IndexField.Collation
Syntax
string Collation
Return Value
Sets or returns the collation of the index field, eg, "en-US". Case-insensitive.
Notes
The collation can only be set for a text field in a btree index.
To change the collation of an existing index field in a table, remove the existing index and then add a new index.
38.2. Schema.IndexField.Descending
Syntax
bool Descending
Return Value
Sets or returns the ordering of the index field. If true, the values of the index field are ordered from largest to smallest, otherwise the values of the index field are ordered from smallest to largest.
Notes
The ordering can only be set for a field in a btree index.
To change the ordering of an existing index field in a table, remove the existing index and then add a new index.
38.3. Schema.IndexField.IgnoreAccent
Syntax
bool IgnoreAccent
Return Value
Sets or returns the accent option of the index field. If true, the values of the index field that only vary in accents are considered to be equal, otherwise such values are considered to be different.
Notes
The accent option can only be set for a text field in a btree index.
To change the accept option of an existing index field in a table, remove the existing index and then add a new index.
38.4. Schema.IndexField.IgnoreCase
Syntax
bool IgnoreCase
Return Value
Sets or returns the case option of the index field. If true, the values of the index field that only vary in case are considered to be equal, otherwise such values are considered to be different.
Notes
The case option can only be set for a text field in a btree index.
To change the case option of an existing index field in a table, remove the existing index and then add a new index.
38.5. Schema.IndexField.IgnoreSymbols
Syntax
bool IgnoreSymbols
Return Value
Sets or returns the symbols option of the index field. If true, the values of the index field that only vary in symbols are considered to be equal, otherwise such values are considered to be different.
Notes
The symbols option can only be set for a text field in a btree index.
To change the symbols option of an existing index field in a table, remove the existing index and then add a new index.
38.6. Schema.IndexField.Name
Syntax
string Name
Return Value
Returns the name of the index field.
38.7. Schema.IndexField.TileReduce
Syntax
string TileReduce
Return Value
Sets or returns the tile reduce mode of the index field. The tile reduce mode specifies the algorithm used to reduce the amount of detail when generating intermediate levels for raster data.
Notes
The tile reduce mode can only be set for a tile field in an rtree index.
Supported tile reduce modes are:
-
"average" - pixel values are averaged,
-
"indexed" - pixel values are sorted by frequency and the most frequent value is used.
To change the tile reduce mode of an existing index field in a table, remove the existing index and then add a new index.
38.8. Schema.IndexField.TileSize
Syntax
string TileSize
Return Value
Sets or returns the tile size of the index field.
Notes
The tile size can only be set for a tile field in an rtree index.
The tile size is specified as "[ x, y ]", with integer components.
To change the tile size of an existing index field in a table, remove the existing index and then add a new index.
38.9. Schema.IndexField.TileType
Syntax
string TileType
Return Value
Sets or returns the type of tile pixel values of the index field.
Notes
The type of tile pixel values can only be set for a tile field in an rtree index.
To access the .NET type used for tile pixel values, use Schema.IndexField.TileTypeClr.
To change the type of tile pixel values of an existing index field in a table, remove the existing index and then add a new index.
38.10. Schema.IndexField.TileTypeClr
Syntax
System.Type TileTypeClr
Return Value
Sets or returns the type of tile pixel values of the index field as a .NET type object.
Notes
The type of tile pixel values can only be set for a tile field in an rtree index.
To access the name of the Manifold type used for tile pixel values, use Schema.IndexField.TileType.
To change the type of tile pixel values of an existing index field in a table, remove the existing index and then add a new index.
39. Schema.IndexFieldSet
39.1. Schema.IndexFieldSet indexers
Syntax
Schema.IndexField object[int index] Schema.IndexField object[string name]
Parameters
index - index of the index field.
name - name of the index field. Case-insensitive.
Return Value
Returns the index field with the specified index or name.
Notes
If the index field is searched by name and there is no index field with the specified name, the method returns a null reference.
39.2. Schema.IndexFieldSet.Count
Syntax
int Count
Return Value
Returns the number of index fields.
40. Schema.IndexSet
40.1. Schema.IndexSet indexers
Syntax
Schema.Index object[int index] Schema.Index object[string name]
Parameters
index - index of the schema index.
name - name of the schema index. Case-insensitive.
Return Value
Returns the schema index with the specified index or name.
Notes
If the index is searched by name and there is no index with the specified name, the method returns a null reference.
40.2. Schema.IndexSet.Count
Syntax
int Count
Return Value
Returns the number of indexes.
41. Sequence
41.1. Sequence.Fetch
Syntax
bool Fetch()
Return Value
Returns true if the sequence fetched values for the next record, otherwise returns false.
Notes
The method attempts to fetch values for the next record in the sequence.
If the method returns false, the sequence has ended. Subsequent attempts to fetch more data will all return false.
Starting to fetch values from a table using a sequence, then altering the table and attempting to use the sequence to fetch more data may result in the sequence returning the old values or the new values or any combination of them, or stopping. The exact behavior depends on the table, the nature of the changes applied to the table, and the type of the sequence.
To access values for the current record, use Sequence.GetValues. To access update values for the current record, use Sequence.GetValuesSec.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { string text = "SELECT * FROM CALL ValueSequence(10, 12, 1)"; using (Manifold.Table table = db.Run(text)) { using (Manifold.Sequence sequence = table.SearchAll(new string[] { "Value" })) { while (sequence.Fetch()) app.Log(sequence.GetValues()[0].Data.ToString()); } } } app.OpenLog(); } // result: 10 // ....... 11 // ....... 12
The above example runs a query that returns a sequence of numbers and reports the returned values.
41.2. Sequence.GetValues
Syntax
ValueSet GetValues()
Return Value
Returns values for the current record.
Notes
If the sequence has never fetched any values or has ended, the method returns a null reference.
The method returns a new value set for each fetched record.
To fetch values for the next record, use Sequence.Fetch. To access update values for the current record, use Sequence.GetValuesSec.
Examples
See examples for Sequence.Fetch.
41.3. Sequence.GetValuesSec
Syntax
ValueSet GetValuesSec()
Return Value
Returns update values for the current record.
Notes
If the sequence has never fetched any values or has ended, the method returns a null reference.
The method returns a new value set for each fetched record.
To fetch values for the next record, use Sequence.Fetch. To access values for the current record, use Sequence.GetValues.
41.4. Sequence.Recompose
Syntax
Sequence Recompose(string[] fields) Sequence Recompose(string[] fields, string[] fieldsSec)
Parameters
fields - list of fields to use for values.
fieldsSec - list of fields to use for update values.
Return Value
Returns a sequence with rearranged values and update values.
Notes
The method creates a new sequence. The values and update values for the new sequence are composed from those of the existing sequence. The method can be used to reduce the number of values returned by an existing sequence, to reorder values, and to convert one or more values into update values or vice versa.
Attempting to use a field that is not in the list of values or update values of the existing sequence will fail.
Attempting to use the same field in both the list of values and the list of update values will fail.
It is possible to use both the new sequence and the existing sequence simultaneously, but fetching values for the next record in one sequence will not update values returned for the current record in the other.
Sequence objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// in a script component named 'Script' in a new MAP file static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) { Manifold.ValueSet values; // request all fields for all records Manifold.Sequence sequence = table.SearchAll(new string[]{ "mfd_id", "name", "type" }); // print all fields for the first record sequence.Fetch(); values = sequence.GetValues(); app.Log(string.Format("{0} : {1} : {2}", values[0].Data, values[1].Data, values[2].Data)); // restrict sequence to just name Manifold.Sequence sequenceNew = sequence.Recompose(new string[]{ "name" }); sequence.Dispose(); // no longer needed sequence = sequenceNew; // print names for all other records while (sequence.Fetch()) { values = sequence.GetValues(); app.Log(string.Format("{0}", values[0].Data)); } sequence.Dispose(); // no longer needed } } app.OpenLog(); } // result: 1 : mfd_root : table // ....... mfd_meta // ....... Script
The above example retrieves all records from the system mfd_root table and restricts the returned sequence to just one field after the first record.
42. Table
42.1. Table.CanDelete
Syntax
bool CanDelete
Return Value
Returns true if the table supports deleting records, otherwise returns false.
Notes
Tables may not support deletes for many reasons. For example, a table may support deletes if the database it is on is opened in read-write mode, but the same table will not support deletes if the database is opened in read-only mode.
Tables in databases for some technologies do not support deletes at all.
To delete a single record, use Table.Delete. To delete multiple records, use Table.DeleteBatch.
Deleting records from a table requires having a unique index. If the table does not have a unique index, the property might return true indicating that the table would support deleting records if it had such an index.
Attempting to delete records from a table may fail even if the table reports that it supports deleting records. For example, attempting to delete records in a table on a SQL Server database might fail due to insufficient permissions, with the property reporting that the table supports deleting records in general.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) app.Log("Deleting records in temporary table: " + (table.CanDelete? "allowed": "disallowed")); using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) app.Log("Deleting records in mfd_root: " + (table.CanDelete? "allowed": "disallowed")); using (Manifold.Table table = db.Search("mfd_meta")) app.Log("Deleting records in mfd_meta: " + (table.CanDelete? "allowed": "disallowed")); } app.OpenLog(); } // result: Deleting records in temporary table: allowed // ....... Deleting records in mfd_root: disallowed // ....... Deleting records in mfd_meta: allowed
The above example checks if it is possible to delete records in a temporary table, in the system mfd_root table, or in the system mfd_meta table.
42.2. Table.CanDesign
Syntax
bool CanDesign
Return Value
Returns true if the table supports changing table schema, otherwise returns false.
Notes
Tables may not support changing table schema for many reasons. For example, a table may support changing schema if the database it is on is opened in read-write mode, but the same table will not support changing schema if the database is opened in read-only mode.
Tables in databases for some technologies do not support changing table schema at all. Tables in databases for other technologies support changing table schema in some ways, but not others.
To change the table schema, use Table.Design. To rename an item in the table schema, use Table.Rename.
Attempting to change the schema of a table may fail even if the table reports that it supports changing schema and even if the specified changes are supported by the database. For example, attempting to change the schema of a table on a SQL Server database might fail due to insufficient permissions, with the property reporting that the table supports changing schema in general.
Examples
// tries to access web server: http://ecn.t*.tiles.virtualearth.net/ (Bing Maps) static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", "http://ecn.t*.tiles.virtualearth.net/tiles/r"); connProperties.SetProperty("SourceSubtype", "bingstreet"); string conn = connProperties.ToJson(); using (Manifold.Database db = app.CreateDatabase("imageserver", conn, true)) { using (Manifold.Table table = db.Search("Bing Maps Street Map")) app.Log("Changing schema of image server table: " + (table.CanDesign? "allowed": "disallowed")); } app.OpenLog(); } // result: Changing schema of image server table: disallowed
The above example attempts to connect to an image server for Bing Maps, retrieves the image table and checks if it supports changing table schema.
42.3. Table.CanGetVersions
Syntax
bool CanGetVersions
Return Value
Returns true if the table tracks changes to data via version numbers, otherwise returns false.
Notes
Tables may or may not track changes to data. Writable tables generally track changes. Read-only tables generally do not track changes.
To get the current version number for a table field, use Table.GetVersionField. To get the current version number for all table records or for a different scope other than a field, use Table.GetVersionScope.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table root = db.Search("mfd_root")) { if (!root.CanGetVersions) app.Log("Root table does not track changes to data"); else { app.Log("Root table tracks changes to data"); app.Log("Table version: " + root.GetVersionScope("VersionTable").ToString()); db.Insert("temporary", "comments"); app.Log("After insert: " + root.GetVersionScope("VersionTable").ToString()); db.Delete("temporary"); app.Log("After delete: " + root.GetVersionScope("VersionTable").ToString()); } } } app.OpenLog(); } // result: Root table tracks changes to data // ....... Table version: 26 // ....... After insert: 29 // ....... After delete: 30
The above example checks if the system mfd_root table tracks changes to data, then tries to insert and delete components (which implicitly changes data in mfd_root) observing changes to version numbers.
42.4. Table.CanInsert
Syntax
bool CanInsert
Return Value
Returns true if the table supports inserting new records, otherwise returns false.
Notes
Tables may not support inserts for many reasons. For example, a table may support inserts if the database it is on is opened in read-write mode, but the same table will not support inserts if the database is opened in read-only mode.
Tables in databases for some technologies do not support inserts at all.
To insert a single record, use Table.Insert. To insert a single record and capture the values for automatically generated fields, use Table.InsertCaptureKeys. To insert multiple records, use Table.InsertBatch.
Inserting records into a table does not require having any indexes. However, if the table has no unique indexes, inserted records cannot be changed and cannot be deleted individually. The table may support deleting all inserted records together with all records that existed prior to the inserts via Table.DeleteAll.
Attempting to insert records into a table may fail even if the table reports that it supports inserting records. For example, attempting to insert records in a table on a SQL Server database might fail due to insufficient permissions, with the property reporting that the table supports inserting records in general.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) app.Log("Inserting records into temporary table: " + (table.CanInsert? "allowed": "disallowed")); using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) app.Log("Inserting records into mfd_root: " + (table.CanInsert? "allowed": "disallowed")); using (Manifold.Table table = db.Search("mfd_meta")) app.Log("Inserting records into mfd_meta: " + (table.CanInsert? "allowed": "disallowed")); } app.OpenLog(); } // result: Inserting records into temporary table: allowed // ....... Inserting records into mfd_root: disallowed // ....... Inserting records into mfd_meta: allowed
The above example checks if it is possible to insert records into a temporary table, into the system mfd_root table, or into the system mfd_meta table.
42.5. Table.CanRename
Syntax
bool CanRename
Return Value
Returns true if the table supports renaming fields, indexes or constraints in the table schema, otherwise returns false.
Notes
Tables may not support renaming table schema items for many reasons. For example, a table may support renaming schema items if the database it is on is opened in read-write mode, but the same table will not support renaming schema items if the database is opened in read-only mode.
Tables in databases for some technologies do not support renaming schema items at all. Tables in databases for other technologies support renaming some schema items, but not others.
To rename an item in the table schema, use Table.Rename. To change the table schema, use Table.Design.
Attempting to renaming a schema item of a table may fail even if the table reports that it supports renaming schema items. For example, attempting to rename a field of a table on a SQL Server database might fail due to insufficient permissions, with the property reporting that the table supports renaming schema items in general.
Examples
// tries to read file: c:\data\mexico.map static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.PropertySet connProperties = app.CreatePropertySet(); connProperties.SetProperty("Source", @"c:\data\mexico.map"); connProperties.SetProperty("SourceReadOnly", true); using (Manifold.Database db = app.CreateDatabase("manifold", connProperties.ToJson(), true)) { using (Manifold.Table table = db.Search("Roads")) app.Log(string.Format("In read-only MAP file, Roads {0} renames of schema items", table.CanRename? "supports": "does not support")); } connProperties.SetProperty("SourceReadOnly", false); using (Manifold.Database db = app.CreateDatabase("manifold", connProperties.ToJson(), true)) { using (Manifold.Table table = db.Search("Roads")) app.Log(string.Format("In writable MAP file, Roads {0} renames of schema items", table.CanRename? "supports": "does not support")); } app.OpenLog(); } // result: In read-only MAP file, Roads does not support renames of schema items // ....... In writable MAP file, Roads supports renames of schema items
The above example connects to a MAP file, opens a table and checks if it supports renaming schema items.
42.6. Table.CanUpdate
Syntax
bool CanUpdate
Return Value
Returns true if the table supports changing record values, otherwise returns false.
Notes
Tables may not support updates for many reasons. For example, a table may support updates if the database it is on is opened in read-write mode, but the same table will not support updates if the database is opened in read-only mode.
Tables in databases for some technologies do not support updates at all.
To update a single record, use Table.Update. To update multiple records, use Table.UpdateBatch.
Updating records in a table requires having a unique index. If the table does not have a unique index, the property might return true indicating that the table would support updating records if it had such an index.
Attempting to update records in a table may fail even if the table reports that it supports updating records. For example, attempting to update records in a table on a SQL Server database might fail due to insufficient permissions, with the property reporting that the table supports updating records in general.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) app.Log("Updating records in temporary table: " + (table.CanUpdate? "allowed": "disallowed")); using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) app.Log("Updating records in mfd_root: " + (table.CanUpdate? "allowed": "disallowed")); using (Manifold.Table table = db.Search("mfd_meta")) app.Log("Updating records in mfd_meta: " + (table.CanUpdate? "allowed": "disallowed")); } app.OpenLog(); } // result: Updating records in temporary table: allowed // ....... Updating records in mfd_root: disallowed // ....... Updating records in mfd_meta: allowed
The above example checks if it is possible to update records in a temporary table, in the system mfd_root table, or in the system mfd_meta table.
42.7. Table.Delete
Syntax
long Delete(string index, ValueSet keys)
Parameters
index - name of a unique index. Case-insensitive.
keys - key values for the record to delete.
Return Value
Returns 1 if the method found and deleted the record with the specified key values. Returns 0 if the method did not find the record with the specified key values.
Notes
The method attempts to delete the record with the specified key values.
The index parameter is the name of a unique index. If the index is not found or is not unique, the method will fail.
The keys parameter provides the key values in the index that identify the record to delete. If the index uses multiple fields, the keys parameter should include values for all of them, otherwise the method will fail. If some of the values for the fields used by the index are NULL, the method will fail. The values in the keys parameter that do not correspond to any of the fields used by the index are ignored.
Attempting to delete a record that does not exist returns 0.
Attempting to delete a record in the system mfd_root table will fail. Using Database.Delete deletes records from the mfd_root table implicitly.
Deleting records in the system mfd_meta table is allowed.
Attempting to delete a record in a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to delete a record without having sufficient permissions will fail.
To check if a table supports deleting records, use Table.CanDelete. To delete all table records, use Table.DeleteAll. To delete multiple records, use Table.DeleteBatch.
When deleting multiple records using the same index, consider using Table.DeleteBatch to improve performance. Alternatively, consider passing key values using a locked value set. To create a locked value set, use ValueSet.CreateLocked.
Examples
// try deleting record static void TryDelete(Manifold.Application app, Manifold.Table table, Manifold.ValueSet keys, string prefix) { try { long result = table.Delete("a_x", keys); app.Log(prefix + ", affected records: " + result.ToString()); } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddIndex("a_x", "btree", new string[] { "a" }); schema.AddField("b", "nvarchar"); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); values.AddValue("b", "text"); table.Insert(values); values[0].Data = 2; // sets "a" to 2 table.Insert(values); // delete record with no keys Manifold.ValueSet keys = app.CreateValueSet(); TryDelete(app, table, keys, "Deleting record with no keys"); // delete non-existing record keys.AddValue("a", 3); TryDelete(app, table, keys, "Deleting non-existing record"); // delete existing record keys[0].Data = 2; TryDelete(app, table, keys, "Deleting existing record"); // delete record that has been deleted already TryDelete(app, table, keys, "Deleting already deleted record"); } app.OpenLog(); } // result: Deleting record with no keys, error: Invalid keys. // ....... Deleting non-existing record, affected records: 0 // ....... Deleting existing record, affected records: 1 // ....... Deleting already deleted record, affected records: 0
The above example creates a new temporary table, overrides its schema, adds several records and tries deleting records with various values of the key fields.
42.8. Table.DeleteAll
Syntax
long DeleteAll()
Return Value
Returns the number of deleted records.
Notes
The method attempts to delete all records in the table.
Deleting all records at once is usually significantly faster than deleting them one by one or even in a batch.
If the table does not have any unique indexes, the method might fail. Some tables allow deleting all records even without indexes.
Attempting to delete all records in a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to delete records without having sufficient permissions will fail.
To check if a table supports deleting records, use Table.CanDelete. To delete a single record, use Table.Delete. To delete multiple specific records, use Table.DeleteBatch.
For more notes on deleting records, see Table.Delete.
Examples
// try deleting all records static void TryDeleteAll(Manifold.Application app, Manifold.Table table, string prefix) { try { long result = table.DeleteAll(); app.Log(prefix + ", affected records: " + result.ToString()); } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema, use no indexes Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); values.AddValue("b", "text"); table.Insert(values); values[0].Data = 2; // sets "a" to 2 table.Insert(values); // delete records without unique index TryDeleteAll(app, table, "Deleting all records without unique index"); // add index schema.AddIndex("a_x", "btree", new string[] { "a" }); table.Design(schema); // delete records with unique index TryDeleteAll(app, table, "Deleting all records with unique index"); } app.OpenLog(); } // result: Deleting all records without unique index, error: Can't delete record. // ....... Deleting all records with unique index, affected records: 2
The above example creates a new temporary table, overrides its schema, adds several records and tries deleting all records with or without a unique index.
42.9. Table.DeleteBatch
Syntax
long DeleteBatch(string index, Sequence sequence)
Parameters
index - name of a unique index. Case-insensitive.
sequence - a sequence with key values for the records to delete.
Return Value
Returns the number of deleted records.
Notes
The method attempts to delete records with the specified key values.
The index parameter is the name of a unique index. If the index is not found or is not unique, the method will fail.
The sequence parameter provides the key values in the index that identify the records to delete. If the index uses multiple fields, the supplied sequence should return values for all of them, otherwise the method will fail and no records will be deleted. The values in the sequence that do not correspond to any of the fields used by the index are ignored.
If fetching data from the supplied sequence fails or if some of the values for the fields used by the index are NULL for one or more records, the method will fail after deleting part of the records. There is no guarantee that all of the records fetched from the sequence prior to the failure will be deleted.
If some of the key values in the supplied sequence do not correspond to an existing record, they are ignored.
Deleting records in a batch is usually significantly faster than deleting them one by one.
Attempting to delete records in a table using a sequence returned by Table.Search, Table.SearchAll or Table.SearchBatch from the same table will produce unpredictable results, including possibly entering an infinite loop, because the table is being both read and written at the same time.
Attempting to delete records in a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to delete records without having sufficient permissions will fail.
To check if a table supports deleting records, use Table.CanDelete. To delete a single record, use Table.Delete. To delete all records, use Table.DeleteAll.
For more notes on deleting records, see Table.Delete.
Examples
// try deleting records static void TryDeleteBatch(Manifold.Application app, Manifold.Table table, Manifold.Sequence sequence, string prefix) { try { long result = table.DeleteBatch("a_x", sequence); app.Log(prefix + ", affected records: " + result.ToString()); } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddIndex("a_x", "btree", new string[] { "a" }); schema.AddField("b", "nvarchar"); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); values.AddValue("b", "text"); table.Insert(values); values[0].Data = 2; // sets "a" to 2 table.Insert(values); values[0].Data = 8; table.Insert(values); values[0].Data = 9; table.Insert(values); values[0].Data = 3; table.Insert(values); // create second temporary table with key values using (Manifold.Table tableDelete = app.CreateTable()) { // override table schema, no need for index, no need for fields other than keys schema = app.CreateSchema(); schema.AddField("a", "int32"); tableDelete.Design(schema); // insert several records with keys from first table values = app.CreateValueSet(); values.AddValue("a", 5); // does not exist tableDelete.Insert(values); values[0].Data = 2; // exists tableDelete.Insert(values); values[0].Data = 1; // exists tableDelete.Insert(values); // delete records with keys listed in second table string[] fields = new string[] { "a" }; using (Manifold.Sequence sequence = tableDelete.SearchAll(fields)) TryDeleteBatch(app, table, sequence, "Deleting batch of records"); } } app.OpenLog(); } // result: Deleting batch of records, affected records: 2
The above example creates a new temporary table, overrides its schema, adds several records, then creates a second temporary table with key values from the first table, and tries deleting records in the first table using key values in the second table.
42.10. Table.Design
Syntax
void Design(Schema schema) void Design(Schema schema, PropertySet properties)
Parameters
schema - new table schema.
properties - additional details for schema changes.
Notes
The method attempts to change the table schema.
Fields in the table that are not in the new schema are removed. If a field being removed is referenced by a constraint or index that is not being removed, the method will fail. If all of the existing fields are being removed, the method will fail. To remove all fields in a table and replace them with one or more new fields, perform the operation in several steps. For example, first add the new fields and then remove the old fields.
Fields in the new schema that are not in the table are added. A new computed field may reference fields that already exist in the table, but not new fields being added. If a new computed field references a field that does not already exist in the table, the method will fail. To add a set of fields that includes computed fields referencing some of the new fields, perform the operation in several steps. For example, first add the fields that are not computed, then add those of the computed fields that reference only the old fields and the added fields, and so on until all fields in the set are added. Circular references between computed fields are disallowed.
Indexes in the table that are not in the new schema are removed.
Indexes in the new schema that are not in the table are added. A new index may reference both the fields that are already in the table and the new fields. If a new index cannot be added because record values do not satisfy the index criteria (for example, the records contain duplicate values in the index fields and the index prohibits that), the method will fail.
Constraints in the table that are not in the new schema are removed.
Constraints in the new schema that are not in the table are added. A new constraint may reference both the fields that are already in the table and the new fields. If a new constraint cannot be added because the constraint expression does not evaluate to true for one or more records, the method will fail.
The table may support changing table schema in some ways, but not others.
If the method is used to perform multiple changes to the table schema and some of these changes fail, changes that were already applied may or may not be rolled back.
To change the type of a field, add a new field with the desired type, copy data from the old field to the new field, delete the old field, then optionally change the name for the new field to the old one using Table.Rename. If the old field is referenced by computed fields, indexes or constraints, they have to be removed and recreated.
Attempting to change the schema of the system mfd_root or mfd_meta table will fail.
Attempting to change the schema of a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to change the schema of a table without having sufficient permissions will fail.
To check if a table supports changing schema, use Table.CanDesign. To rename an item in the table schema, use Table.Rename.
Examples
// report table schema static string ReportSchema(Manifold.Table table) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); Manifold.Schema schema = table.GetSchema(); if (schema.Fields.Count > 0) { builder.Append("Fields: "); for (int index = 0; index < schema.Fields.Count; ++index) builder.Append((index > 0? ", ": "") + schema.Fields[index].Name); builder.Append(". "); } if (schema.Indexes.Count > 0) { builder.Append("Indexes: "); for (int index = 0; index < schema.Indexes.Count; ++index) builder.Append((index > 0? ", ": "") + schema.Indexes[index].Name); builder.Append(". "); } if (schema.Constraints.Count > 0) { builder.Append("Constraints: "); for (int index = 0; index < schema.Constraints.Count; ++index) builder.Append((index > 0? ", ": "") + schema.Constraints[index].Name); builder.Append(". "); } return builder.ToString(); } // try changing table schema static void TryDesign(Manifold.Application app, Manifold.Table table, Manifold.Schema schema, string action) { app.Log(action); try { table.Design(schema); app.Log(" Success: " + ReportSchema(table)); } catch (System.Exception e) { app.Log(" Error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // report schema for default in-memory table app.Log("Initial schema: " + ReportSchema(table)); // add several fields Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); TryDesign(app, table, schema, "Adding two fields"); // add btree index schema = table.GetSchema(); schema.AddIndex("a_x", "btree", new string[] { "a" }); TryDesign(app, table, schema, "Adding btree index"); // add geom field and rtree index on it schema = table.GetSchema(); schema.AddField("g", "geom"); schema.AddIndex("g_x", "rtree", new string[] { "g" }); TryDesign(app, table, schema, "Adding geom field and rtree index"); // add computed field, fails because temporary table returned by // app.CreateTable does not support computed fields or constraints schema = table.GetSchema(); schema.AddFieldComputed("f", "int32", "a + 100"); TryDesign(app, table, schema, "Trying to add computed field"); // delete geom field, rejected by index referencing that field schema = table.GetSchema(); schema.DeleteField("g"); TryDesign(app, table, schema, "Trying to delete geom field"); // delete geom field and rtree index on it schema = table.GetSchema(); schema.DeleteIndex("g_x"); schema.DeleteField("g"); TryDesign(app, table, schema, "Deleting geom field and rtree index"); } app.OpenLog(); } // result: Initial schema: Fields: mfd_id. Indexes: mfd_id_x. // ....... Adding two fields // ....... Success: Fields: mfd_id, a, b. Indexes: mfd_id_x. // ....... Adding btree index // ....... Success: Fields: mfd_id, a, b. Indexes: mfd_id_x, a_x. // ....... Adding geom field and rtree index // ....... Success: Fields: mfd_id, a, b, g. Indexes: mfd_id_x, a_x, g_x. // ....... Trying to add computed field // ....... Error: Invalid object reference. // ....... Trying to delete geom field // ....... Error: Can't delete field. // ....... Deleting geom field and rtree index // ....... Success: Fields: mfd_id, a, b. Indexes: mfd_id_x, a_x.
The above example creates a new temporary table and tries changing its schema in various ways.
Temporary tables created via Application.CreateTable do not support computed fields or constraints.
// report table schema static string ReportSchema(Manifold.Table table) { System.Text.StringBuilder builder = new System.Text.StringBuilder(); Manifold.Schema schema = table.GetSchema(); if (schema.Fields.Count > 0) { builder.Append("Fields: "); for (int index = 0; index < schema.Fields.Count; ++index) builder.Append((index > 0? ", ": "") + schema.Fields[index].Name); builder.Append(". "); } if (schema.Indexes.Count > 0) { builder.Append("Indexes: "); for (int index = 0; index < schema.Indexes.Count; ++index) builder.Append((index > 0? ", ": "") + schema.Indexes[index].Name); builder.Append(". "); } if (schema.Constraints.Count > 0) { builder.Append("Constraints: "); for (int index = 0; index < schema.Constraints.Count; ++index) builder.Append((index > 0? ", ": "") + schema.Constraints[index].Name); builder.Append(". "); } return builder.ToString(); } // try changing table schema static void TryDesign(Manifold.Application app, Manifold.Table table, Manifold.Schema schema, string action) { app.Log(action); try { table.Design(schema); app.Log(" Success: " + ReportSchema(table)); } catch (System.Exception e) { app.Log(" Error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { // add table with default field and index Manifold.Schema schema = app.CreateSchema(); schema.AddField("mfd_id", "int64"); schema.AddIndex("mfd_id_x", "btree", new string[] { "mfd_id" }); string inserted = db.Insert("t", "table", schema); using (Manifold.Table table = db.Search(inserted)) { app.Log("Inserted schema: " + ReportSchema(table)); // add several fields schema = table.GetSchema(); schema.AddField("a", "int32"); schema.AddField("b", "nvarchar"); TryDesign(app, table, schema, "Adding two fields"); // add btree index schema = table.GetSchema(); schema.AddIndex("a_x", "btree", new string[] { "a" }); TryDesign(app, table, schema, "Adding btree index"); // add geom field and rtree index on it schema = table.GetSchema(); schema.AddField("g", "geom"); schema.AddIndex("g_x", "rtree", new string[] { "g" }); TryDesign(app, table, schema, "Adding geom field and rtree index"); // add computed field schema = table.GetSchema(); schema.AddFieldComputed("f", "int32", "a + 100"); TryDesign(app, table, schema, "Adding computed field"); // adding constraint schema = table.GetSchema(); schema.AddConstraint("f_c", "f >= 0"); TryDesign(app, table, schema, "Adding constraint on computed field"); // add several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); values.AddValue("b", "text"); table.Insert(values); values[0].Data = 2; // sets "a" to 2 table.Insert(values); values[0].Data = 3; // sets "a" to 3 table.Insert(values); // add constraint, fails because records do not satisfy it schema = table.GetSchema(); schema.AddConstraint("g_c", "g IS NOT NULL"); TryDesign(app, table, schema, "Trying to add constraint on geom field"); } } app.OpenLog(); } // result: Inserted schema: Fields: mfd_id. Indexes: mfd_id_x. // ....... Adding two fields // ....... Success: Fields: mfd_id, a, b. Indexes: mfd_id_x. // ....... Adding btree index // ....... Success: Fields: mfd_id, a, b. Indexes: mfd_id_x, a_x. // ....... Adding geom field and rtree index // ....... Success: Fields: mfd_id, a, b, g. Indexes: mfd_id_x, a_x, g_x. // ....... Adding computed field // ....... Success: Fields: mfd_id, a, b, g, f. Indexes: mfd_id_x, a_x, g_x. // ....... Adding constraint on computed field // ....... Success: Fields: mfd_id, a, b, g, f. Indexes: mfd_id_x, a_x, g_x. Constraints: f_c. // ....... Trying to add constraint on geom field // ....... Error: Can't add constraint.
The above example creates a new temporary database and a new table on that database, then tries changing its schema in various ways.
42.11. Table.GetSchema
Syntax
Schema GetSchema()
Return Value
Returns the table schema.
Notes
The returned schema lists fields, indexes and constraints in the table. A table always has at least one field.
To check if a table supports changing schema, use Table.CanDesign. To change the table schema, use Table.Design. To rename an item in the table schema, use Table.Rename.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_meta")) { Manifold.Schema schema = table.GetSchema(); foreach (Manifold.Schema.Field field in schema.Fields) app.Log(field.Name + " : " + field.Type); } } app.OpenLog(); } // result: mfd_id : int64 // ....... Name : nvarchar // ....... Property : nvarchar // ....... Value : nvarchar
The above example retrieves the schema of the system mfd_meta table and reports its fields with field types.
42.12. Table.GetVersionField
Syntax
long GetVersionField(string field)
Parameters
field - field name. Case-insensitive.
Return Value
Returns the current version number for values in the specified field.
Notes
Tables may or may not track changes to data. Writable tables generally track changes. Read-only tables generally do not track changes.
If the table does not track changes to data, the method returns 0.
If the field name is invalid, the method returns 0.
Version numbers are opaque values and are only intended to be compared for equality. Updating values of one or more fields in a record changes version numbers for the updated fields and for computed fields that depend on them. Deleting a record does not change version numbers for any fields. Inserting a new record changes version numbers for the fields which receive the inserted values specified explicitly and for computed fields that depend on them.
Version numbers are not guaranteed to persist between sessions. Tables in MAP files persist version numbers between sessions, tables in other databases usually start with a new set of version numbers for each session.
To check if a table tracks changes to data via version numbers, use Table.CanGetVersions. To get the current version number for all table records or for a different scope other than a field, use Table.GetVersionScope.
Examples
// report versions of 'a' and 'b' static void ReportVersions(Manifold.Application app, Manifold.Table table, string prefix) { app.Log(string.Format("{0}: version of a = {1}, version of b = {2}", prefix, table.GetVersionField("a"), table.GetVersionField("b"))); } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { // add table with custom schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("mfd_id", "int64"); schema.AddIndex("mfd_id_x", "btree", new string[] { "mfd_id" }); schema.AddField("a", "nvarchar"); schema.AddFieldComputed("b", "nvarchar", "StringToUpperCase(a)"); string inserted = db.Insert("t", "table", schema); using (Manifold.Table table = db.Search(inserted)) { if (!table.CanGetVersions) app.Log("Table does not track changes to data"); else { ReportVersions(app, table, "On start"); // insert record Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("mfd_id", 1); // to find record later values.AddValue("a", "xyz"); table.Insert(values); ReportVersions(app, table, "After inserting record"); // update record Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("mfd_id", 1); values = app.CreateValueSet(); values.AddValue("a", "xyz new"); table.Update("mfd_id_x", keys, values); ReportVersions(app, table, "After updating record"); // delete record table.Delete("mfd_id_x", keys); ReportVersions(app, table, "After deleting record"); } } } app.OpenLog(); } // result: On start: version of a = 0, version of b = 0 // ....... After inserting record: version of a = 1, version of b = 1 // ....... After updating record: version of a = 2, version of b = 2 // ....... After deleting record: version of a = 2, version of b = 2
The above example creates a new temporary database and a new table on that database, then inserts, updates and deletes records in that table observing changes to field version numbers.
42.13. Table.GetVersionScope
Syntax
long GetVersionScope(string scope)
Parameters
scope - scope name, eg, "versiontable". Case-insensitive.
Return Value
Returns the current version number for values in the specified scope.
Notes
Tables may or may not track changes to data. Writable tables generally track changes. Read-only tables generally do not track changes.
If the table does not track changes to data, the method returns 0.
If the scope name is invalid, the method returns 0.
Supported scope names are:
-
"versiontable" - changes when table is being changed in any way.
-
"versiontablefields" - changes when table fields are being added or deleted.
-
"versiontablerecords" - changes when table records are being added or deleted.
-
"versiontablestore" - changes when table fields are being added or deleted, when table records are being added or deleted, and when table record values are being changed.
Version numbers are opaque values and are only intended to be compared for equality.
Version numbers are not guaranteed to persist between sessions. Tables in MAP files persist version numbers between sessions, tables in other databases usually start with a new set of version numbers for each session.
To check if a table tracks changes to data via version numbers, use Table.CanGetVersions. To get the current version number for a table field, use Table.GetVersionScope.
Examples
// report versions of various table scopes static void ReportVersions(Manifold.Application app, Manifold.Table table, string prefix) { app.Log(string.Format("{0}: version of table = {1}, fields = {2}, records = {3}, store = {4}", prefix, table.GetVersionScope("VersionTable"), table.GetVersionScope("VersionTableFields"), table.GetVersionScope("VersionTableRecords"), table.GetVersionScope("VersionTableStore"))); } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "nvarchar"); table.Design(schema); if (!table.CanGetVersions) app.Log("Table does not track changes to data"); else { ReportVersions(app, table, "On start"); // insert record Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("mfd_id", 1); // to find record later values.AddValue("a", "xyz"); table.Insert(values); ReportVersions(app, table, "After inserting record"); // add field schema.AddField("b", "nvarchar"); table.Design(schema); ReportVersions(app, table, "After adding field"); // update record Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("mfd_id", 1); values = app.CreateValueSet(); values.AddValue("a", "xyz new"); table.Update("mfd_id_x", keys, values); ReportVersions(app, table, "After updating record"); // delete record table.Delete("mfd_id_x", keys); ReportVersions(app, table, "After deleting record"); } } app.OpenLog(); } // result: On start: version of table = 4, fields = 2, records = 0, store = 2 // ....... After inserting record: version of table = 6, fields = 2, records = 1, store = 4 // ....... After adding field: version of table = 8, fields = 3, records = 1, store = 5 // ....... After updating record: version of table = 9, fields = 3, records = 1, store = 6 // ....... After deleting record: version of table = 10, fields = 3, records = 2, store = 7
The above example creates a new temporary table, overrides its schema, then inserts, updates and deletes records in that table and changes the table schema, observing changes to version numbers.
42.14. Table.Insert
Syntax
long Insert(ValueSet values)
Parameters
values - values for a new record.
Return Value
Returns 1 if the method inserted a record with the specified values. If a record cannot be inserted, the method fails and an exception is thrown.
Notes
The method attempts to insert a new record.
The values parameter provides field values for the new record. The provided values should not include values for computed fields and for other read-only fields. If the provided values include values for such fields, the method will fail. The provided values do not have to include values for all writable fields. Fields with no provided values will be set by the table - usually, to NULL values. If the provided values include values that do not correspond to any field, the method will fail.
Attempting to insert a record with values that make one or more of the computed fields fail to compute will fail.
Attempting to insert a record with values that fail one or more table constraints will fail.
Attempting to insert a record with values that fail the criteria for one or more table indexes will fail.
Attempting to insert a record into the system mfd_root table will fail. Using Database.Insert inserts records into the mfd_root table implicitly.
Inserting records into the system mfd_meta table is allowed.
Attempting to insert a record into a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to insert a record without having sufficient permissions will fail.
To check if a table supports inserting records, use Table.CanInsert. To insert a single record and capture the values for automatically generated fields, use Table.InsertCaptureKeys. To insert multiple records, use Table.InsertBatch.
When inserting multiple records, consider using Table.InsertBatch to improve performance. Alternatively, consider passing inserted values using a locked value set. To create a locked value set, use ValueSet.CreateLocked.
Examples
// try inserting record static void TryInsert(Manifold.Application app, Manifold.Table table, Manifold.ValueSet values, string prefix) { try { long result = table.Insert(values); app.Log(prefix + ", affected records: " + result.ToString()); } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { // add table with custom schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("mfd_id", "int64"); schema.AddIndex("mfd_id_x", "btree", new string[] { "mfd_id" }); schema.AddField("a", "int32"); schema.AddFieldComputed("b", "int32", "100 / a"); schema.AddConstraint("a_c", "a < 10"); schema.AddConstraint("b_c", "b IS NOT NULL"); string inserted = db.Insert("t", "table", schema); using (Manifold.Table table = db.Search(inserted)) { // insert record with autogenerated mfd_id Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); TryInsert(app, table, values, "Inserting record with autogenerated mfd_id"); // insert record with specific mfd_id values = app.CreateValueSet(); values.AddValue("mfd_id", 50); values.AddValue("a", 2); TryInsert(app, table, values, "Inserting record with specific mfd_id"); // insert record with duplicate mfd_id values = app.CreateValueSet(); values.AddValue("mfd_id", 50); values.AddValue("a", 3); TryInsert(app, table, values, "Inserting record with duplicate mfd_id"); // insert record with values that does not satisfy constraint values = app.CreateValueSet(); values.AddValue("a", 15); TryInsert(app, table, values, "Inserting record that does not pass a_c"); // insert record with values that does not satisfy constraint on computed field values = app.CreateValueSet(); values.AddValue("a", 0); // b = 100 / 0 = NULL TryInsert(app, table, values, "Inserting record that does not pass b_c"); } } app.OpenLog(); } // result: Inserting record with autogenerated mfd_id, affected records: 1 // ....... Inserting record with specific mfd_id, affected records: 1 // ....... Inserting record with duplicate mfd_id, error: Cannot add record. // ....... Inserting record that does not pass a_c, error: Cannot add record. // ....... Inserting record that does not pass b_c, error: Cannot add record.
The above example creates a new temporary database and a new table on that database, then tries to insert records into the table with various values.
42.15. Table.InsertBatch
Syntax
long InsertBatch(Sequence sequence)
Parameters
sequence - a sequence with values for the records to insert.
Return Value
Returns the number of inserted records.
Notes
The method attempts to insert records with the specified values.
The sequence parameter provides values for the new records. The provided values should not include values for computed fields and for other read-only fields. If the provided values include values for such fields, the method will fail. The provided values do not have to include values for all writable fields. Fields with no provided values will be set by the table - usually, to NULL values. If the provided values include values that do not correspond to any field, the method will fail.
If fetching data from the supplied sequence fails or if the values for one or more records fail to insert, the method will fail after inserting part of the records. There is no guarantee that all of the records fetched from the sequence prior to the failure will be inserted.
Inserting records in a batch is usually significantly faster than inserting them one by one.
Attempting to insert records into a table using a sequence returned by Table.Search, Table.SearchAll or Table.SearchBatch from the same table will produce unpredictable results, including possibly entering an infinite loop, because the table is being both read and written at the same time.
Attempting to insert records into a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to insert records without having sufficient permissions will fail.
To check if a table supports inserting records, use Table.CanInsert. To insert a single record, use Table.Insert. To insert a single record and capture the values for automatically generated fields, use Table.InsertCaptureKeys.
For more notes on inserting records, see Table.Insert.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = app.CreateTable()) { // temporary table has mfd_id // insert multiple records into temporary table string query = "SELECT value AS mfd_id FROM CALL ValueSequence(10, 13, 1)"; using (Manifold.Table tableRun = db.Run(query)) { using (Manifold.Sequence sequence = tableRun.SearchAll(new string[] { "mfd_id" })) table.InsertBatch(sequence); } // list table records using (Manifold.Sequence sequence = table.SearchAll(new string[] { "mfd_id" })) { while (sequence.Fetch()) app.Log(sequence.GetValues()[0].Data.ToString()); } } } app.OpenLog(); } // result: 10 // ....... 11 // ....... 12 // ....... 13
The above example creates a new temporary table with the default mfd_id field, then runs a query that returns a sequence of values and inserts that data into the temporary table.
42.16. Table.InsertCaptureKeys
Syntax
long InsertCaptureKeys(ValueSet values, string index, ValueSet keys)
Parameters
values - values for a new record.
index - name of a unique index with the fields to capture. Case-insensitive.
keys - values for the captured fields, set by the method.
Return Value
Returns 1 if the method inserted a record with the specified values and captured values for the fields in the specified index. If a record cannot be inserted, the method fails and an exception is thrown.
Notes
The method attempts to insert a new record and capture values for the fields in the specified index. The fields in the index might be autogenerated.
The values parameter provides field values for the new record. The provided values should not include values for computed fields and for other read-only fields. If the provided values include values for such fields, the method will fail. The provided values do not have to include values for all writable fields. Fields with no provided values will be set by the table - usually, to NULL values, or, in the case of autogenerated fields, to the next unique value. If the provided values include values that do not correspond to any field, the method will fail.
The index parameter is the name of a unique index. If the index is not found or is not unique, the method will fail.
The keys parameter is set by the method. If the method succeeds, the parameter contains values for the fields in the specified index.
The method is usually used to insert a record and determine the values that have been assigned to the autogenerated fields for that record. When the method is used in that way, the values parameter is set to not include the values for the autogenerated fields. If the method succeeds, the values for the autogenerated fields are returned in keys.
Some autogenerated fields allow writes, others are read-only. Tables in MAP files support the system mfd_id field, which is autogenerated and allows writes.
Attempting to insert a record into a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to insert a record without having sufficient permissions will fail.
To check if a table supports inserting records, use Table.CanInsert. To insert a single record, use Table.Insert. To insert multiple records, use Table.InsertBatch.
When inserting multiple records capturing values for the fields in a specific index, consider passing inserted values using a locked value set. To create a locked value set, use ValueSet.CreateLocked.
For more notes on inserting records, see Table.Insert.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // temporary table has mfd_id // insert a record, capture the value of mfd_id Manifold.ValueSet keys = app.CreateValueSet(); Manifold.ValueSet values = app.CreateValueSet(); table.InsertCaptureKeys(values, "mfd_id_x", keys); app.Log("Inserted record: " + keys[0].Name + " = " + keys[0].Data.ToString()); } app.OpenLog(); } // result: Inserted record: mfd_id = 1
The above example creates a new temporary table with the default mfd_id field, inserts a record and captures the value of the mfd_id field assigned to that record.
42.17. Table.Rename
Syntax
void Rename(string nameNew, string name)
Parameters
nameNew - new name. Case-insensitive.
name - name of a field, index or constraint. Case-insensitive.
Notes
The method attempts to rename an item in the table schema.
The table may support renaming some items in the table schema, but not others.
Attempting to rename a schema item to the name of another schema item will fail.
Attempting to rename a schema item in the system mfd_root or mfd_meta table will fail.
Attempting to rename a system schema item like mfd_id or mfd_id_x will fail.
Attempting to rename a schema item in a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to rename a schema item without having sufficient permissions will fail.
To check if a table supports renaming schema items, use Table.CanRename. To change the table schema, use Table.Design.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "int32"); table.Design(schema); // insert record Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("mfd_id", 1); values.AddValue("a", 10); table.Insert(values); app.Log("Inserted value as a: 10"); // rename field table.Rename("b", "a"); app.Log("Renamed a to b"); // read value from renamed field Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("mfd_id", 1); using (Manifold.Sequence sequence = table.Search("mfd_id_x", keys, new string[] { "b" })) { sequence.Fetch(); app.Log("Read value as b: " + sequence.GetValues()[0].Data.ToString()); } } app.OpenLog(); } // result: Inserted value as a: 10 // ....... Renamed a to b // ....... Read value as b: 10
The above example creates a new temporary database and a new table on that database, adds a record, then renames a field and reads the added value back from the renamed field.
42.18. Table.Search
Syntax
Sequence Search(string index, ValueSet keys, string[] fields)
Parameters
index - name of a unique index. Case-insensitive.
keys - key values for the record to locate.
fields - list of fields to return. May be empty.
Return Value
Returns a sequence with a single record if the method found the record. Returns a sequence with no records or a null reference if the method did not find the record.
Notes
The method attempts to locate the record with the specified key values.
The index parameter is the name of a unique index. If the index is not found or is not unique, the method will fail.
The keys parameter provides the key values in the index that identify the record to locate. The values in the keys parameter that do not correspond to any of the fields used by the index are ignored.
The fields parameter is a list of fields to return. The list of fields may be empty. If one or more fields in the list is not found, the method will fail. If one or more fields in the list is included multiple times, the method will fail. The sequence returned by the method returns exactly the same fields as specified in the list, in the order of the list.
Attempting to locate a record that does not exist returns a sequence with no records or a null reference.
Databases for some technologies control access to components via permissions. Attempting to locate or read a record without having sufficient permissions will fail.
To return all records in a table, use Table.SearchAll. To search for multiple records using an index, use Table.SearchBatch.
When searching for records using the same index with varying key values, consider passing key values using a locked value set. To create a locked value set, use ValueSet.CreateLocked.
Sequence objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// try locating record static void TrySearch(Manifold.Application app, Manifold.Table table, Manifold.ValueSet keys, string prefix) { try { using (Manifold.Sequence sequence = table.Search("mfd_id_x", keys, new string[] { "a" })) { if (sequence == null || !sequence.Fetch()) app.Log(prefix + ": not found"); else app.Log(prefix + ": found, a = " + sequence.GetValues()[0].Data.ToString()); } } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "int32"); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("mfd_id", 1); values.AddValue("a", 10); table.Insert(values); values[0].Data = 2; values[1].Data = 20; table.Insert(values); values[0].Data = 3; values[1].Data = 30; table.Insert(values); // search for record with no key Manifold.ValueSet keys = app.CreateValueSet(); TrySearch(app, table, keys, "Searching with no key"); // search for record with key that does not exist keys.AddValue("mfd_id", 500); TrySearch(app, table, keys, "Searching with key that does not exist"); // search for record with key that exists keys[0].Data = 2; TrySearch(app, table, keys, "Searching with valid key"); } app.OpenLog(); } // result: Searching with no key: not found // ....... Searching with key that does not exist: not found // ....... Searching with valid key: found, a = 20
The above example creates a new temporary table, overrides its schema, inserts several records, then tries to search for them with various keys.
42.19. Table.SearchAll
Syntax
Sequence SearchAll(string[] fields)
Parameters
fields - list of fields to return. May be empty.
Return Value
Returns a sequence with table records if the table contains one or more records. Returns a sequence with no records or a null reference if the table contains no records.
Notes
The method attempts to return all table records.
The fields parameter is a list of fields to return. The list of fields may be empty. If one or more fields in the list is not found, the method will fail. If one or more fields in the list is included multiple times, the method will fail. The sequence returned by the method returns exactly the same fields as specified in the list, in the order of the list.
Reading table records using the sequence returned by this method is frequently significantly faster than reading them using the sequence returned by Table.SearchBatch.
The order of records in the sequence returned by this method is random.
Databases for some technologies control access to components via permissions. Attempting to read records without having sufficient permissions will fail.
To locate a single record in a table, use Table.Search. To search for multiple records using an index, use Table.SearchBatch.
Sequence objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "int32"); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("mfd_id", 1); values.AddValue("a", 10); table.Insert(values); values[0].Data = 3; values[1].Data = 30; table.Insert(values); values[0].Data = 2; values[1].Data = 20; table.Insert(values); // read all records using (Manifold.Sequence sequence = table.SearchAll(new string[] { "mfd_id", "a" })) { if (sequence != null) { while (sequence.Fetch()) app.Log(string.Format("{0} : {1}", sequence.GetValues()[0].Data, sequence.GetValues()[1].Data)); } } } app.OpenLog(); } // result: 1 : 10 // ....... 2 : 20 // ....... 3 : 30
The above example creates a new temporary table, overrides its schema, adds several records, then reads all records in the table.
42.20. Table.SearchBatch
Syntax
Sequence SearchBatch(string index, ValueSet keys, string[] fields)
Parameters
index - name of an index. Case-insensitive.
keys - key values specifying the search criteria.
fields - list of fields to return. May be empty.
Return Value
Returns a sequence with table records if the search criteria matches one or more records. Returns a sequence with no records or a null reference if the search criteria matches no records.
Notes
The method attempts to locate records that match the specified search criteria.
The index parameter is the name of an index. If the index is not found, the method will fail.
The keys parameter provides the key values specifying the search criteria. The key values are interpreted according to the index type.
BTREE / BTREEDUP / BTREEDUPNULL / BTREENULL indexes interpret key values as the starting point of the search.
-
For an index that uses a single field:
If the provided values do not include the value for the index field, the returned sequence starts at the record with the smallest value of the index field according to the index field options.
If the provided values include the value for the index field, the returned sequence starts at the record with the specified value. If there are no records with the value of the index field equal to the specified value, the returned sequence starts at the record with the smallest value of the index field greater than the specified value according to the index field options (next larger value).
-
For an index that uses multiple fields:
If the provided values do not include the value for the first index field, the returned sequence starts at the record with the smallest value of the index fields according to the index field options. The values in the index fields are compared in the order of fields specified by the index until the first pair of values that are not equal to each other according to the index field options.
If the provided values include the value for the first index field but do not include the values for all index fields, the returned sequence starts at the record with the smallest value of the index fields greater than the specified value according to the index field options (next larger value).
If the provided values include values for all index fields, the returned sequence starts at the record with the specified value. If there are no records with the value of the index fields equal to the specified value, the returned sequence starts at the record with the smallest value of the index fields greater than the specified value according to the index field options (next larger value).
If the index allows duplicates and there are multiple records sharing the values of the index fields on which the sequence should start, the sequence is guaranteed to read through all of these records.
The index may reverse the ordering in one or more fields via field options.
The values in the keys parameter that do not correspond to any of the fields used by the index are ignored.
The order of records in the returned sequence proceeds from smaller to larger values of the index fields according to the index field options.
If the index starts at the record with the smallest value of the index fields according to the index field options, the returned sequence will proceed through all table records.
In the index that allows NULL values, records with NULL values appear after records with non-NULL values. Searching for a NULL value in a specific field or fields is impossible. (In order to find the boundary between non-NULL and NULL values, search for the maximum allowed value of the index fields. If there are no records with that value, the returned sequence will be positioned on the first record with a NULL value in the first index field. If there are records with the maximum allowed value of the index fields, the returned sequence will have to be fetched until the first record with a NULL value in the first index field.)
RTREE indexes interpret key values as the rectangular area for the search.
If the provided values do not include the value for the geometry field, the method returns a sequence with no records or a null reference.
If the provided values include the value for the geometry field, that value should be convertible to FLOAT64X4. If the value is not convertible to FLOAT64X4, the method returns a sequence with no records or a null reference. The FLOAT64X4 value defines a rectangle, with the values interpreted as XMIN, YMIN, XMAX, YMAX in order. If the FLOAT64X4 value defines an invalid rectangle (XMIN > XMAX or YMIN > YMAX), the method returns a sequence with no records or a null reference. If the FLOAT64X4 value defines a valid rectangle, the method returns a sequence with the records for geometry values that have any part of the bounding box within that rectangle.
The values in the keys parameter other than the value for the geometry field are ignored.
The order of records in the returned sequence is random.
The index cannot generally be used to return all table records. If the rectangular area for the search includes all geometry values in all table records, the returned sequence will proceed through these records but records with NULL geometry values will be skipped.
The fields parameter is a list of fields to return. The list of fields may be empty. If one or more fields in the list is not found, the method will fail. If one or more fields in the list is included multiple times, the method will fail. The sequence returned by the method returns exactly the same fields as specified in the list, in the order of the list.
Databases for some technologies control access to components via permissions. Attempting to read records without having sufficient permissions will fail.
To specify additional options when searching for multiple records using an index, use Table.SearchBatchBTree, Table.SearchBatchRTree or Table.SearchBatchRTreeThin. To locate a single record in a table, use Table.Search. To return all records in a table, use Table.SearchAll.
When searching for records using the same index with varying key values, consider passing key values using a locked value set. To create a locked value set, use ValueSet.CreateLocked.
Sequence objects are expensive. It is best to dispose of them immediately after they are no longer needed.
Examples
// in a script component named 'Script' in a new MAP file // list records in sequence static void ListSequence(Manifold.Application app, Manifold.Sequence sequence) { if (sequence == null) return; using (sequence) { while (sequence.Fetch()) app.Log(" " + sequence.GetValues()[0].Data.ToString()); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_root")) { string[] fields = new string[] { "name" }; // list all records Manifold.ValueSet keys = app.CreateValueSet(); app.Log("Listing all records in order of 'name_x' (ordered by 'name')"); ListSequence(app, table.SearchBatch("name_x", keys, fields)); // list all records starting with specified value keys.AddValue("name", "mfd_root"); app.Log("Listing records starting with 'mfd_root'"); ListSequence(app, table.SearchBatch("name_x", keys, fields)); // list all records starting with non-existing value keys[0].Data = "new_component"; app.Log("Listing records starting with 'new_component'"); ListSequence(app, table.SearchBatch("name_x", keys, fields)); } } app.OpenLog(); } // result: Listing all records in order of 'name_x' (ordered by 'name') // ....... mfd_meta // ....... mfd_root // ....... Script // ....... Listing records starting with 'mfd_root' // ....... mfd_root // ....... Script // ....... Listing records starting with 'new_component' // ....... Script
The above example lists records in the system mfd_root table using a btree index on the name field.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = db.Search("mfd_meta")) { // request name and value for output // request property to determine when sequence crosses into next property string[] fields = new string[] { "name", "property", "value" }; // search for records with property >= 'Folder' Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("property", "Folder"); using (Manifold.Sequence sequence = table.SearchBatch("property_name_x", keys, fields)) { if (sequence != null) { while (sequence.Fetch()) { Manifold.ValueSet values = sequence.GetValues(); // stop if crossed into next property string prop = values[1].Data.ToString(); if (prop.ToLower() != "folder") break; app.Log(string.Format("{0} : {1}", values[0].Data, values[2].Data)); } } } } } app.OpenLog(); } // result: mfd_meta : System Data // ....... mfd_root : System Data
The above example lists components with the 'Folder' property in the system mfd_meta table using a btree index on the property and name fields with a partial key, passing just the value for the property field.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddIndex("a_x", "btreedupnull", new string[] { "a" }); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); table.Insert(values); // NULL values.AddValue("a", 1); table.Insert(values); // 1 table.Insert(values); // 1 (second) values = app.CreateValueSet(); table.Insert(values); // NULL (second) values.AddValue("a", 2); table.Insert(values); // 2 values[0].Data = 0; table.Insert(values); // 0 app.Log("Listing records starting with 1"); // return records starting with 1 Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("a", 1); using (Manifold.Sequence sequence = table.SearchBatch("a_x", keys, new string[] { "a" })) { if (sequence != null) { while (sequence.Fetch()) { object value = sequence.GetValues()[0].Data; app.Log(" " + (value == null? "<NULL>": value.ToString())); } } } } app.OpenLog(); } // result: Listing records starting with 1 // ....... 1 // ....... 1 // ....... 2 // ....... <NULL> // ....... <NULL>
The above example creates a new temporary table, overrides its schema adding a numeric field and a btree index that allows duplicates and NULLs on that field, fills the table with some values and searches the table using the index.
Attempting to search for a value that appears in the index more than once returns all records with that value.
NULL values appear last.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("g", "geom"); schema.AddIndex("g_x", "rtree", new string[] { "g" }); table.Design(schema); // insert rectangular grid of points Manifold.GeomBuilder builder = app.CreateGeomBuilder(); Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("g"); for (int x = 1; x <= 3; ++x) { for (int y = 1; y <= 3; ++y) { builder.StartGeomPoint(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(x, y)); builder.EndBranch(); values[0].Data = builder.EndGeom(); table.Insert(values); } } app.Log("Listing points in rectangle"); // search for points in rectangle Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("g", new Manifold.Point4<double>(1.5, 1.5, 4, 4)); using (Manifold.Sequence sequence = table.SearchBatch("g_x", keys, new string[] { "g" })) { if (sequence != null) { while (sequence.Fetch()) { values = sequence.GetValues(); Manifold.Geom geom = values[0].Data as Manifold.Geom; if (geom == null) app.Log(" <NULL>"); else app.Log(" " + geom.Coords[0].ToString()); } } } } app.OpenLog(); } // result: Listing points in rectangle // ....... [ 2, 2 ] // ....... [ 2, 3 ] // ....... [ 3, 2 ] // ....... [ 3, 3 ]
The above example creates a new tempory table, overrides its schema adding a geom field and an rtree index on that field, fills the table with a rectangular grid of points, then searches the table using the index to return points in a rectangular area.
42.21. Table.SearchBatchBTree
Syntax
Sequence SearchBatchBTree(string index, ValueSet keys, string[] fields, bool ascending)
Parameters
index - name of a btree index. Case-insensitive.
keys - key values specifying the search criteria.
fields - list of fields to return. May be empty.
ascending - if true, the index is searched from smaller to larger values according to the index field options, otherwise the index is searched from larger to smaller values.
Return Value
Returns a sequence with table records if the search criteria matches one or more records. Returns a sequence with no records or a null reference if the search criteria matches no records.
Notes
The method attempts to locate records that match the specified search criteria with additional options.
If the index is not a btree index, the method will fail.
The order of records in the returned sequence coincides with the index search direction.
For more details, see notes for Table.SearchBatch.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("a", "int32"); schema.AddIndex("a_x", "btree", new string[] { "a" }); table.Design(schema); // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); for (int index = 0; index < 5; ++index) { values[0].Data = index; table.Insert(values); } for (int run = 0; run < 2; ++run) { bool ascending = (run == 0); app.Log(string.Format("Listing records starting with 1 in {0} order", ascending? "ascending": "descending")); // return records starting with 1 Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("a", 1); using (Manifold.Sequence sequence = table.SearchBatchBTree("a_x", keys, new string[] { "a" }, ascending)) { if (sequence != null) { while (sequence.Fetch()) app.Log(" " + sequence.GetValues()[0].Data.ToString()); } } } } app.OpenLog(); } // result: Listing records starting with 1 in ascending order // ....... 1 // ....... 2 // ....... 3 // ....... 4 // ....... Listing records starting with 1 in descending order // ....... 1 // ....... 0
The above example creates a new temporary table, adds a numeric field and a btree index on that field, fills the table with a sequence of numbers and searches the table using the index in both directions.
42.22. Table.SearchBatchRTree
Syntax
Sequence SearchBatchRTree(string index, ValueSet keys, string[] fields, bool touching)
Parameters
index - name of an rtree index. Case-insensitive.
keys - key values specifying the bounding box of the search area.
fields - list of fields to return. May be empty.
touching - if true, the search returns records with values with any part of the bounding box in the search area, otherwise the search returns records with values with the bounding box entirely within the search area.
Return Value
Returns a sequence with table records if the search criteria matches one or more records. Returns a sequence with no records or a null reference if the search criteria matches no records.
Notes
The method attempts to locate records that match the specified search criteria with additional options.
If the index is not an rtree index, the method will fail.
For more details, see notes for Table.SearchBatch.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("g", "geom"); schema.AddIndex("g_x", "rtree", new string[] { "g" }); table.Design(schema); // insert rectangular grid of rects Manifold.GeomBuilder builder = app.CreateGeomBuilder(); Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("g"); for (int x = 1; x <= 3; ++x) { for (int y = 1; y <= 3; ++y) { builder.StartGeomArea(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(x, y)); builder.AddCoord(new Manifold.Point<double>(x + 1, y)); builder.AddCoord(new Manifold.Point<double>(x + 1, y + 1)); builder.AddCoord(new Manifold.Point<double>(x, y + 1)); builder.EndBranch(); values[0].Data = builder.EndGeom(); table.Insert(values); } } // compose search rectangle Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("g", new Manifold.Point4<double>(1.5, 1.5, 3.5, 3.5)); // search for areas touching rectangle app.Log("Listing areas touching the rectangle"); using (Manifold.Sequence sequence = table.SearchBatchRTree("g_x", keys, new string[] { "g" }, true)) { if (sequence != null) { while (sequence.Fetch()) { values = sequence.GetValues(); Manifold.Geom geom = values[0].Data as Manifold.Geom; Manifold.Geom.CoordSet coords = geom.Coords; app.Log(" " + coords[0].ToString() + " : " + coords[2].ToString()); } } } // search for areas entirely within rectangle app.Log("Listing areas entirely within the rectangle"); using (Manifold.Sequence sequence = table.SearchBatchRTree("g_x", keys, new string[] { "g" }, false)) { if (sequence != null) { while (sequence.Fetch()) { values = sequence.GetValues(); Manifold.Geom geom = values[0].Data as Manifold.Geom; Manifold.Geom.CoordSet coords = geom.Coords; app.Log(" " + coords[0].ToString() + " : " + coords[2].ToString()); } } } } app.OpenLog(); } // result: Listing areas touching the rectangle // ....... [ 1, 1 ] : [ 2, 2 ] // ....... [ 1, 2 ] : [ 2, 3 ] // ....... [ 1, 3 ] : [ 2, 4 ] // ....... [ 2, 1 ] : [ 3, 2 ] // ....... [ 2, 2 ] : [ 3, 3 ] // ....... [ 2, 3 ] : [ 3, 4 ] // ....... [ 3, 1 ] : [ 4, 2 ] // ....... [ 3, 2 ] : [ 4, 3 ] // ....... [ 3, 3 ] : [ 4, 4 ] // ....... Listing areas entirely within the rectangle // ....... [ 2, 2 ] : [ 3, 3 ]
The above example creates a new tempory table, adds a geom field and an rtree index on that field, fills the table with a rectangular grid of areas and searches the table using the index first for areas touching the search area and then for areas contained in the search area.
42.23. Table.SearchBatchRTreeThin
Syntax
Sequence SearchBatchRTreeThin(string index, ValueSet keys, string[] fields, bool touching, int cx, int cy, bool allowReduce)
Parameters
index - name of an rtree index. Case-insensitive.
keys - key values specifying the bounding box of the search area.
fields - list of fields to return. May be empty.
touching - if true, the search returns records with values with any part of the bounding box in the search area, otherwise the search returns records with values with the bounding box entirely within the search area.
cx - number of cells in the search area by X.
cy - number of cells in the search area by Y.
allowReduce - if true, the search may reduce returned geometry values according to the search resolution, otherwise the search returns unmodified geometry values.
Return Value
Returns a sequence with table records if the search criteria matches one or more records. Returns a sequence with no records or a null reference if the search criteria matches no records.
Notes
The method attempts to locate records that match the specified search criteria with additional options.
If the index is not an rtree index, the method will fail.
If the index does not support thinning, the method returns the same data as Table.SearchBatchRTree.
For more details, see notes for Table.SearchBatch.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // override table schema Manifold.Schema schema = table.GetSchema(); schema.AddField("g", "geom"); schema.AddIndex("g_x", "rtree", new string[] { "g" }); table.Design(schema); // insert three points on top of each other Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomPoint(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.EndBranch(); Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("g", builder.EndGeom()); table.Insert(values); table.Insert(values); table.Insert(values); // compose search rectangle Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("g", new Manifold.Point4<double>(0, 0, 2, 2)); // search for points without thinning app.Log("Listing points in the rectangle"); using (Manifold.Sequence sequence = table.SearchBatchRTree("g_x", keys, new string[] { "g" }, true)) { if (sequence != null) { while (sequence.Fetch()) { values = sequence.GetValues(); Manifold.Geom geom = values[0].Data as Manifold.Geom; Manifold.Geom.CoordSet coords = geom.Coords; app.Log(" " + coords[0].ToString()); } } } // search for points with thinning app.Log("Listing points in the rectangle with thinning"); using (Manifold.Sequence sequence = table.SearchBatchRTreeThin("g_x", keys, new string[] { "g" }, true, 100, 100, false)) { if (sequence != null) { while (sequence.Fetch()) { values = sequence.GetValues(); Manifold.Geom geom = values[0].Data as Manifold.Geom; Manifold.Geom.CoordSet coords = geom.Coords; app.Log(" " + coords[0].ToString()); } } } } app.OpenLog(); } // result: Listing points in the rectangle // ....... [ 1, 1 ] // ....... [ 1, 1 ] // ....... [ 1, 1 ] // ....... Listing points in the rectangle with thinning // ....... [ 1, 1 ]
The above example creates a new tempory table, adds a geom field and an rtree index on that field, adds several records with points and searches the table using the index with and without thinning.
42.24. Table.Update
Syntax
long Update(string index, ValueSet keys, ValueSet values)
Parameters
index - name of a unique index. Case-insensitive.
keys - key values for the record to update.
values - values to update.
Return Value
Returns 1 if the method found the record with the specified key values and updated it. If a record cannot be found or updated, the method fails and an exception is thrown.
Notes
The method attempts to update the record with the specified key values.
The index parameter is the name of a unique index. If the index is not found or is not unique, the method will fail.
The keys parameter provides the key values in the index that identify the record to update. If the index uses multiple fields, the keys parameter should include values for all of them, otherwise the method will fail. If some of the values for the fields used by the index are NULL, the method will fail. The values in the keys parameter that do not correspond to any of the fields used by the index are ignored.
The values parameter provides the values to update. The provided values should not include values for computed fields and for other read-only fields. If the provided values include values for such fields, the method will fail.
Attempting to update a record that does not exist will fail.
Attempting to update a record with values that make one or more of the computed fields fail to compute will fail.
Attempting to update a record with values that fail one or more table constraints will fail.
Attempting to update a record with values that fail the criteria for one or more table indexes will fail.
Attempting to update a record in the system mfd_root table will fail.
Updating records in the system mfd_meta table is allowed.
Attempting to update a record in a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to update a record without having sufficient permissions will fail.
To check if a table supports updating records, use Table.CanUpdate. To update multiple records, use Table.UpdateBatch.
When updating multiple records using the same index, consider using Table.UpdateBatch to improve performance. Alternatively, consider passing key values and update values using locked value sets. To create a locked value set, use ValueSet.CreateLocked.
Examples
// try updating record static void TryUpdate(Manifold.Application app, Manifold.Table table, int id, Manifold.ValueSet values, string prefix) { try { Manifold.ValueSet keys = app.CreateValueSet(); keys.AddValue("mfd_id", id); long result = table.Update("mfd_id_x", keys, values); app.Log(prefix + ", affected records: " + result.ToString()); } catch (System.Exception e) { app.Log(prefix + ", error: " + e.Message); } } static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.CreateDatabase()) { // add table with custom schema Manifold.Schema schema = app.CreateSchema(); schema.AddField("mfd_id", "int64"); schema.AddIndex("mfd_id_x", "btree", new string[] { "mfd_id" }); schema.AddField("a", "int32"); schema.AddFieldComputed("b", "int32", "a / 10"); schema.AddIndex("b_x", "btree", new string[] { "b" }); string inserted = db.Insert("t", "table", schema); using (Manifold.Table table = db.Search(inserted)) { // insert several records Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("mfd_id", 1); values.AddValue("a", 10); table.Insert(values); values[0].Data = 2; values[1].Data = 20; table.Insert(values); values[0].Data = 3; values[1].Data = 30; table.Insert(values); // update record values = app.CreateValueSet(); values.AddValue("a", 40); TryUpdate(app, table, 2, values, "Updating record"); // update record to duplicate mfd_id, rejected by index values = app.CreateValueSet(); values.AddValue("mfd_id", 1); TryUpdate(app, table, 2, values, "Updating record to duplicate mfd_id"); // update record to duplicate value of computed field, rejected by index values = app.CreateValueSet(); values.AddValue("a", 30); TryUpdate(app, table, 2, values, "Updating record to duplicate b"); } } app.OpenLog(); } // result: Updating record, affected records: 1 // ....... Updating record to duplicate mfd_id, error: Duplicate key field value. // ....... Updating record to duplicate b, error: Duplicate key field value.
The above example creates a new temporary database and a new table on that database, inserts several records, then tries updating records with various values.
42.25. Table.UpdateBatch
Syntax
long UpdateBatch(string index, Sequence sequence)
Parameters
index - name of a unique index. Case-insensitive.
sequence - a sequence with key values for the records to update, and the values to update.
Return Value
Returns the number of updated records.
Notes
The method attempts to update records with the specified key values.
The index parameter is the name of a unique index. If the index is not found or is not unique, the method will fail.
The sequence parameter provides the key values in the index that identify the records to update as well as the values to update. The key values are supplied in Sequence.GetValues and the values to update are supplied in Sequence.GetValuesSec. If the index uses multiple fields, Sequence.GetValues should return values for all of them, otherwise the method will fail and no records will be updated. The values in Sequence.GetValues that do not correspond to any of the fields used by the index are ignored.
If fetching data from the supplied sequence fails or if the values for one or more records fail to update, the method will fail after updating part of the records. There is no guarantee that all of the records fetched from the sequence prior to the failure will be updated.
If some of the key values in the supplied sequence do not correspond to an existing record, the method will fail.
Updating records in a batch is usually significantly faster than updating them one by one.
Attempting to update records in a table using a sequence returned by Table.Search, Table.SearchAll or Table.SearchBatch from the same table will produce unpredictable results, including possibly entering an infinite loop, because the table is being both read and written at the same time.
Attempting to update records in a table on a database opened in read-only mode will fail.
Databases for some technologies control access to components via permissions. Attempting to update records without having sufficient permissions will fail.
To check if a table supports updating records, use Table.CanUpdate. To update a single record, use Table.Update.
For more notes on updating records, see Table.Update.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Database db = app.GetDatabaseRoot()) { using (Manifold.Table table = app.CreateTable()) { // add integer field in addition to mfd_id Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "int32"); table.Design(schema); // insert multiple records into temporary table string queryInsert = "SELECT value AS mfd_id, value AS a FROM CALL ValueSequence(1, 10, 1)"; using (Manifold.Table tableRun = db.Run(queryInsert)) { using (Manifold.Sequence sequence = tableRun.SearchAll(new string[] { "mfd_id", "a" })) table.InsertBatch(sequence); } // update even records in temporary table string queryUpdate = "SELECT value AS mfd_id, value + 100 AS a FROM CALL ValueSequence(2, 10, 2)"; using (Manifold.Table tableRun = db.Run(queryUpdate)) { using (Manifold.Sequence sequence = tableRun.SearchAll(new string[] { "mfd_id", "a" })) using (Manifold.Sequence sequenceUpdate = sequence.Recompose( new string[]{ "mfd_id" }, // keys of records to update new string[]{ "a" })) // values to update table.UpdateBatch("mfd_id_x", sequenceUpdate); } // list table records using (Manifold.Sequence sequence = table.SearchAll(new string[] { "mfd_id", "a" })) { while (sequence.Fetch()) { Manifold.ValueSet values = sequence.GetValues(); app.Log(string.Format("{0} : {1}", values[0].Data, values[1].Data)); } } } } app.OpenLog(); } // result: 1 : 1 // ....... 2 : 102 // ....... 3 : 3 // ....... 4 : 104 // ....... 5 : 5 // ....... 6 : 106 // ....... 7 : 7 // ....... 8 : 108 // ....... 9 : 9 // ....... 10 : 110
The above example creates a new temporary table with the default mfd_id field and a new integer field. The example inserts multiple records into the table, then updates half of them.
43. Tile
43.1. Tile.GetBytes
Syntax
byte[] GetBytes()
Return Value
Returns the binary representation of the tile value.
Notes
Each call to the method returns a new object.
To convert the binary representation back to a tile value, use TypeConverter.Convert.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(128, 128, "uint8x3"); Manifold.Tile tile = builder.EndTile(); app.Log(string.Format("Blank tile ({0}x{1}, {2}): {3} bytes", tile.Width, tile.Height, tile.Type, tile.GetBytes().Length)); app.OpenLog(); } // result: Blank tile (128x128, uint8x3): 16 bytes
The above example composes a blank tile and reports its dimensions, pixel type, and the number of bytes in its binary representation.
43.2. Tile.Height
Syntax
int Height
Return Value
Returns the number of pixels along the vertical axis of the tile value.
43.3. Tile.PixelMissingMasks
Syntax
Tile.PixelSet<bool> PixelMissingMasks
Return Value
Returns pixel missing masks of the tile value.
Notes
If the missing mask of a pixel is true, the pixel is missing / invisible.
If the missing mask of a pixel is false, the pixel is available / visible.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(1, 1, "uint8x3"); Manifold.Tile tile = builder.EndTile(); app.Log(tile.PixelMissingMasks[0, 0]? "Invisible": "Visible"); app.OpenLog(); } // result: Visible
The above example composes a blank tile with UINT8X3 pixels and reports the missing mask of a tile pixel.
43.4. Tile.Pixels
Syntax
Tile.PixelSet<T> Pixels
COM languages:
Tile.PixelSet<T> PixelObjs
Return Value
Returns pixels of the tile value.
Notes
The returned object has to be cast to the variant of Tile.PixelSet for the type corresponding to the type of pixels in the tile value.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(1, 1, "uint8x3"); Manifold.TileBuilder.PixelSet<Manifold.Point3<byte>> builderPixels = (Manifold.TileBuilder.PixelSet<Manifold.Point3<byte>>)builder.Pixels; builderPixels[0, 0] = new Manifold.Point3<byte>(128, 128, 128); Manifold.Tile tile = builder.EndTile(); Manifold.Tile.PixelSet<Manifold.Point3<byte>> pixels = (Manifold.Tile.PixelSet<Manifold.Point3<byte>>)tile.Pixels; app.Log(pixels[0, 0].ToString()); app.OpenLog(); } // result: [ 128, 128, 128 ]
The above example composes a tile with UINT8X3 pixels and reports the value of a tile pixel.
43.5. Tile.Type
Syntax
string Type
Return Value
Returns the name of the Manifold type used for pixels in the tile value.
Notes
To get the .NET type used for pixels in the tile value, use Tile.TypeClr. To convert pixel values of a tile to a different type, use TypeConverter.ConvertTilePixels.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(1, 1, "uint8x3"); Manifold.Tile tile = builder.EndTile(); app.Log(tile.Type); app.OpenLog(); } // result: uint8x3
The above example composes a blank tile with UINT8X3 pixels and reports the type of pixel values.
43.6. Tile.TypeClr
Syntax
System.Type TypeClr
Return Value
Returns the .NET type used for pixels in the tile value.
Notes
To get the name of the Manifold type used for pixels in the tile value, use Tile.Type. To convert pixel values of a tile to a different type, use TypeConverter.ConvertTilePixels.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(1, 1, "uint8x3"); Manifold.Tile tile = builder.EndTile(); app.Log(tile.TypeClr.ToString()); app.OpenLog(); } // result: Manifold.Point3`1[System.Byte]
The above example composes a blank tile with UINT8X3 pixels and reports the .NET type of pixel values.
43.7. Tile.Width
Syntax
int Width
Return Value
Returns the number of pixels along the horizontal axis of the tile value.
44. Tile.PixelSet
44.1. Tile.PixelSet indexers
Syntax
T object[int x, int y]
Parameters
x - X coordinate of the pixel value, 0-based.
y - Y coordinate of the pixel value, 0-based.
Return Value
Returns the value of the pixel with the specified coordinates.
45. TileBuilder
45.1. TileBuilder.EndTile
Syntax
Tile EndTile()
Return Value
Returns the composed tile value.
Notes
The method finishes editing the current tile value and returns it. The tile builder is cleared.
If the tile builder does not contain a tile value, the method returns a null reference.
Examples
See examples for TileBuilder.StartTile.
45.2. TileBuilder.Height
Syntax
int Height
Return Value
Returns the number of pixels along the vertical axis of the current tile value.
Notes
If the tile builder does not contain a tile value, the method returns 0.
45.3. TileBuilder.PixelMissingMasks
Syntax
TileBuilder.PixelSet<bool> PixelMissingMasks
Return Value
Returns pixel missing masks of the current tile value.
Notes
If the missing mask of a pixel is true, the pixel is missing / invisible.
If the missing mask of a pixel is false, the pixel is available / visible.
The original values of missing pixels may not be saved in the tile.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; for (int run = 0; run < 2; ++run) { Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(3, 3, "uint8"); // filled with 0 Manifold.TileBuilder.PixelSet<byte> builderPixels = (Manifold.TileBuilder.PixelSet<byte>)builder.Pixels; builderPixels[1, 1] = 255; if (run == 1) builder.PixelMissingMasks[1, 1] = true; // invisible Manifold.Tile tile = builder.EndTile(); Manifold.Tile.PixelSet<byte> pixels = (Manifold.Tile.PixelSet<byte>)tile.Pixels; app.Log(string.Format("Run {0}, pixel is {1}, pixel value is {2}", run, tile.PixelMissingMasks[1, 1]? "invisible": "visible", pixels[1, 1])); } app.OpenLog(); } // result: Run 0, pixel is visible, pixel value is 255 // ....... Run 1, pixel is invisible, pixel value is 0
The above example demonstrates how making a pixel invisible might lose its original value.
45.4. TileBuilder.Pixels
Syntax
TileBuilder.PixelSet<T> Pixels
COM languages:
TileBuilder.PixelSet<T> PixelObjs
Return Value
Returns pixels of the current tile value.
Notes
The returned object has to be cast to the variant of TileBuilder.PixelSet for the type corresponding to the type of pixels in the current tile value.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(15, 15, "float32"); Manifold.TileBuilder.PixelSet<float> builderPixels = (Manifold.TileBuilder.PixelSet<float>)builder.Pixels; for (int y = 0; y < builder.Height; ++y) { for (int x = 0; x < builder.Width; ++x) builderPixels[x, y] = (float)(x*x + y*y); } Manifold.Tile tile = builder.EndTile(); Manifold.Tile.PixelSet<float> pixels = (Manifold.Tile.PixelSet<float>)tile.Pixels; app.Log(pixels[4, 7].ToString()); app.OpenLog(); } // result: 65
The above example composes a tile filled with a radial pattern and reports the value of a tile pixel.
45.5. TileBuilder.StartTile
Syntax
void StartTile(int width, int height, string type) void StartTile(int width, int height, System.Type type)
Parameters
width - the number of pixels along the horizontal axis of the new tile value.
height - the number of pixels along the vertical axis of the new tile value.
type - type of pixels in the new tile value. Can be either a .NET type object or a string with the name of the Manifold type.
Notes
The method starts building a new tile value with the specified dimensions and pixel type. The pixel values are intially set to 0. The pixel missing masks are initially set to false (all pixels visible).
If the tile builder contains a tile value, all data for that value is removed.
To start building a tile using a copy of an existing tile, use TileBuilder.StartTileCopy. To get the dimensions of the current tile, use TileBuilder.Width and TileBuilder.Height. To get the type of pixel values, use TileBuilder.Type or TileBuilder.TypeClr. To access pixel values, use TileBuilder.Pixels. To access pixel missing masks, use TileBuilder.PixelMissingMasks. To finish the current tile value, use TileBuilder.EndTile.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(3, 3, "uint8"); // filled with 0 Manifold.TileBuilder.PixelSet<byte> builderPixels = (Manifold.TileBuilder.PixelSet<byte>)builder.Pixels; for (int y = 0; y < builder.Height; ++y) { byte value = y == 0? (byte)128: y == 1? (byte)192: (byte)255; for (int x = 0; x < builder.Width; ++x) builderPixels[x, y] = value; } Manifold.Tile tile = builder.EndTile(); Manifold.Tile.PixelSet<byte> pixels = (Manifold.Tile.PixelSet<byte>)tile.Pixels; for (int y = 0; y < tile.Height; ++y) { for (int x = 0; x < tile.Width; ++x) app.Log(string.Format("[ {0}, {1} ] : {2}", x, y, pixels[x, y])); } app.OpenLog(); } // result: [ 0, 0 ] : 128 // ....... [ 1, 0 ] : 128 // ....... [ 2, 0 ] : 128 // ....... [ 0, 1 ] : 192 // ....... [ 1, 1 ] : 192 // ....... [ 2, 1 ] : 192 // ....... [ 0, 2 ] : 255 // ....... [ 1, 2 ] : 255 // ....... [ 2, 2 ] : 255
The above example composes a new tile and fills it with a vertical gradient.
45.6. TileBuilder.StartTileCopy
Syntax
void StartTileCopy(Tile tile)
Parameters
tile - tile to copy.
Notes
The method starts building a new tile value. The dimensions, pixel type, pixel values and pixel missing masks of the new tile are copied from the specified tile.
If the tile builder contains a tile value, all data for that value is removed.
To start building a new tile using explicit dimensions and pixel type, use TileBuilder.StartTile. To get the dimensions of the current tile, use TileBuilder.Width and TileBuilder.Height. To get the type of pixel values, use TileBuilder.Type or TileBuilder.TypeClr. To access pixel values, use TileBuilder.Pixels. To access pixel missing masks, use TileBuilder.PixelMissingMasks. To finish the current tile value, use TileBuilder.EndTile.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.TileBuilder builder = app.CreateTileBuilder(); // create blank tile builder.StartTile(3, 3, "uint8"); // filled with 0 Manifold.TileBuilder.PixelSet<byte> builderPixels = (Manifold.TileBuilder.PixelSet<byte>)builder.Pixels; Manifold.Tile tile = builder.EndTile(); Manifold.Tile.PixelSet<byte> pixels = (Manifold.Tile.PixelSet<byte>)tile.Pixels; app.Log(string.Format("Original: {0}", pixels[1, 1])); // edit pixel builder.StartTileCopy(tile); builderPixels = (Manifold.TileBuilder.PixelSet<byte>)builder.Pixels; // new object builderPixels[1, 1] = 255; tile = builder.EndTile(); pixels = (Manifold.Tile.PixelSet<byte>)tile.Pixels; // new object app.Log(string.Format("Edited: {0}", pixels[1, 1])); app.OpenLog(); } // result: Original: 0 // ....... Edited: 255
The above example composes a new blank tile, then makes a copy of it and edits the value of a pixel.
45.7. TileBuilder.Type
Syntax
string Type
Return Value
Returns the name of the Manifold type used for pixels in the current tile value.
Notes
If the tile builder does not contain a tile value, the method returns a null reference.
To get the .NET type used for pixels in the current tile value, use TileBuilder.TypeClr. To convert pixel values of a tile to a different type, use TypeConverter.ConvertTilePixels.
45.8. TileBuilder.TypeClr
Syntax
System.Type TypeClr
Return Value
Returns the .NET type used for pixels in the current tile value.
Notes
If the tile builder does not contain a tile value, the method returns a null reference.
To get the name of the Manifold type used for pixels in the current tile value, use TileBuilder.Type. To convert pixel values of a tile to a different type, use TypeConverter.ConvertTilePixels.
45.9. TileBuilder.Width
Syntax
int Width
Return Value
Returns the number of pixels along the horizontal axis of the current tile value.
Notes
If the tile builder does not contain a tile value, the method returns 0.
46. TileBuilder.PixelSet
46.1. TileBuilder.PixelSet indexers
Syntax
T object[int x, int y]
Parameters
x - X coordinate of the pixel value, 0-based.
y - Y coordinate of the pixel value, 0-based.
Return Value
Sets or returns the value of the pixel with the specified coordinates.
47. TypeConverter
47.1. TypeConverter.Convert
Syntax
object Convert(object value, string type) object Convert(object value, System.Type type)
COM languages (using this variant of the method is only required when converting a value to or from one of the Point<T>, Point3<T> or Point4<T> generic types):
object ConvertObj(object value, string type)
Parameters
value - value to convert.
type - type to convert to. Can be either a .NET type object or a string with the name of the Manifold type.
Return Value
Returns the converted value. Returns a null reference if the conversion can not be performed.
Notes
If the value parameter is a null reference, the method will fail.
If the type parameter does not correspond to a valid Manifold type, the method will fail.
To get a .NET type object for the Manifold type with the specified name, use TypeConverter.GetTypeClr. To get the name of a Manifold type used for values of the specified .NET type, use TypeConverter.GetTypeManifold.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { double value = 1.0 / 3.0; app.Log(converter.Convert(value, "nvarchar").ToString()); } app.OpenLog(); } // result: 0.3333333333333333
The above example computes the floating-point value of 1/3, converts it into a string value and reports the result.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { Manifold.Point<int> value = new Manifold.Point<int>(1, 2); app.Log(converter.Convert(value, "int32x3").ToString()); } app.OpenLog(); } // result: [1, 2, 0]
The above example composes a point value with two coordinates, converts it into a point value with three coordinates and reports the result.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { Manifold.GeomBuilder builder = app.CreateGeomBuilder(); builder.StartGeomLine(); builder.AddBranch(); builder.AddCoord(new Manifold.Point<double>(1, 1)); builder.AddCoord(new Manifold.Point<double>(2, 2)); builder.EndBranch(); Manifold.Geom geom = builder.EndGeom(); object converted = converter.Convert(geom, typeof(Manifold.GeomWkb)); app.Log(converted == null? "<NULL>": converted.ToString()); } app.OpenLog(); } // result: Manifold.GeomWkb
The above example composes a geom value, converts it to a geom WKB value and reports the result.
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { byte[] value = new byte[] { 0, 0, 0, 0 }; object converted = converter.Convert(value, typeof(Manifold.GeomWkb)); app.Log(converted == null? "<NULL>": converted.ToString()); } app.OpenLog(); } // result: <NULL>
The above example composes a sequence of zero bytes, attempts to convert it to a geom WKB value and reports the result.
47.2. TypeConverter.ConvertTilePixels
Syntax
Tile ConvertTilePixels(Tile tile, string type) Tile ConvertTilePixels(Tile tile, System.Type type)
Parameters
tile - tile with the pixel values to convert.
type - type to convert pixel values to. Can be either a .NET type object or a string with the name of the Manifold type.
Return Value
Returns a tile with the converted pixel values. Returns a null reference if the conversion can not be performed.
Notes
If the value parameter is a null reference, the method will fail.
If the type parameter does not correspond to a valid Manifold type, the method will fail.
The returned tile has the same dimensions as the original tile.
To determine the type of pixel values in a tile, use Tile.Type or Tile.TypeClr. To get a .NET type object for the Manifold type with the specified name, use TypeConverter.GetTypeClr. To get the name of a Manifold type used for values of the specified .NET type, use TypeConverter.GetTypeManifold.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) { Manifold.TileBuilder builder = app.CreateTileBuilder(); builder.StartTile(3, 3, "int8"); Manifold.TileBuilder.PixelSet<sbyte> builderPixels = (Manifold.TileBuilder.PixelSet<sbyte>)builder.Pixels; builderPixels[1, 1] = -1; Manifold.Tile tile = builder.EndTile(); Manifold.Tile converted = converter.ConvertTilePixels(tile, "uint8"); Manifold.Tile.PixelSet<byte> pixels = (Manifold.Tile.PixelSet<byte>)converted.Pixels; app.Log(pixels[1, 1].ToString()); } app.OpenLog(); } // result: 255
The above example composes a tile with INT8 pixels, converts it to a tile with UINT8 pixels and reports the value of a pixel in the converted tile.
47.3. TypeConverter.GetTypeClr
Syntax
System.Type GetTypeClr(string type)
Parameters
type - name of the Manifold type. Case-insensitive.
Return Value
Returns a .NET type object for the Manifold type with the specified name. Returns a null reference if the name does not correspond to a valid Manifold type.
Notes
The values of some Manifold types are represented using the same .NET type. For example, the values of both VARCHAR and NVARCHAR Manifold types are represented as System.String.
To get the name of a Manifold type used for values of the specified .NET type, use TypeConverter.GetTypeManifold.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) app.Log(converter.GetTypeClr("tile").ToString()); app.OpenLog(); } // result: Manifold.Tile
The above example determines the .NET type used to represent values of the Manifold TILE type.
47.4. TypeConverter.GetTypeManifold
Syntax
string GetTypeManifold(System.Type type)
Parameters
type - .NET type object.
Return Value
Returns the name of a Manifold type used for values of the specified .NET type. Returns a null reference if the values of the specified .NET type do not correspond to any Manifold type.
Notes
To get a .NET type object for the Manifold type with the specified name, use TypeConverter.GetTypeClr.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.TypeConverter converter = app.CreateTypeConverter()) app.Log(converter.GetTypeManifold(typeof(bool))); app.OpenLog(); } // result: boolean
The above example determines the name of the Manifold type used to represent .NET boolean values.
48. Value
48.1. Value.Data
Syntax
object Data
COM languages (using this variant of the property is only required with the value of one of the Point<T>, Point3<T> or Point4<T> generic types):
object DataObj
Return Value
Sets or returns the data associated with the value.
48.2. Value.Name
Syntax
string Name
Return Value
Returns the name of the value.
48.3. Value.Type
Syntax
string Type
Return Value
Returns the name of the Manifold type for the data associated with the value. Returns the default type assigned to the value if the value has no associated data.
48.4. Value.TypeClr
Syntax
System.Type TypeClr
Return Value
Returns the .NET type of the data associated with the value. Returns the default type assigned to the value if the value has no associated data.
49. ValueSet
49.1. ValueSet indexers
Syntax
Value object[int index] Value object[string name]
Parameters
index - index of the value.
name - name of the value. Case-insensitive.
Return Value
Returns the value with the specified index or name.
Notes
If the value is searched by name and there is no value with the specified name, the method returns a null reference.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); values.AddValue("b", 2); for (int index = 0; index < values.Count; ++index) app.Log(values[index].Name); app.OpenLog(); } // result: a // ....... b
The above example creates a value set, fills it with example values and reports the name of each value.
49.2. ValueSet.AddValue
Syntax
void AddValue(string name) void AddValue(string name, object data)
COM languages (using this variant of the method is only required with the initial data of one of the Point<T>, Point3<T> or Point4<T> generic types):
void AddValueObj(string name, object data)
Parameters
name - name of the value to add. Case-insensitive.
data - initial data for the value.
Notes
The method adds a new value with the specified name. If the value with the specified name already exists, the method will fail. The new value has no default type.
If the value set is locked, the method will fail.
To add a new value with the default type, use ValueSet.AddValueType. To delete a value, use ValueSet.DeleteValue. To delete all values, use ValueSet.Clear. To determine the index of the value with the specified name, use ValueSet.FindValue. To check if the value with the specified name already exists, use ValueSet.HasValue.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a", 1); values.AddValue("b"); values.AddValueType("c", typeof(string)); foreach (Manifold.Value value in values) app.Log(string.Format("{0} : {1} : {2}", value.Name, value.Data == null? "<NULL>": value.Data.ToString(), value.Type == null? "<NULL>": value.Type)); app.OpenLog(); } // result: a : 1 : int32 // ....... b : <NULL> : <NULL> // ....... c : <NULL> : nvarchar
The above example creates a value set, fills it with example values and reports the contents of each value.
49.3. ValueSet.AddValueType
Syntax
void AddValueType(string name, string type) void AddValueType(string name, System.Type type)
Parameters
name - name of the value to add. Case-insensitive.
type - default type. Can be either a .NET type object or a string with the name of the Manifold type.
Notes
The method adds a new value with the specified name and default type. If the value with the specified name already exists, the method will fail.
If the value set is locked, the method will fail.
Values with the default type are commonly used to pass type info to expressions without creating model data values.
To add a new value without the default type, use ValueSet.AddValue. To delete a value, use ValueSet.DeleteValue. To delete all values, use ValueSet.Clear. To determine the index of the value with the specified name, use ValueSet.FindValue. To check if the value with the specified name exists, use ValueSet.HasValue.
Examples
See examples for ValueSet.AddValue and ExpressionParser.CreateExpression.
49.4. ValueSet.Clear
Syntax
void Clear()
Notes
Deletes all values.
If the value set is locked, the method will fail.
To add a new value, use ValueSet.AddValue or ValueSet.AddValueType. To delete a specific value, use ValueSet.DeleteValue. To determine the index of the value with the specified name, use ValueSet.FindValue. To check if the value with the specified name exists, use ValueSet.HasValue.
49.5. ValueSet.Count
Syntax
int Count
Return Value
Returns the number of values.
49.6. ValueSet.CreateCopy
Syntax
ValueSet CreateCopy(bool copyData)
Parameters
copyData - if true, copies data values, otherwise only copies the name and default type for each value.
Return Value
Returns a new value set with the same values as the original value set.
Notes
The returned value set is writable and can be altered independently from the original value set.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); values.AddValue("b"); values.AddValue("c"); Manifold.ValueSet valuesCopy = values.CreateCopy(false); app.Log("Original values: " + values.Count.ToString()); app.Log("Copied values: " + valuesCopy.Count.ToString()); app.OpenLog(); } // result: Original values: 3 // ....... Copied values: 3
The above example creates a value set, fills it with example values, then creates its copy and reports the number of values in each set.
49.7. ValueSet.CreateLocked
Syntax
ValueSet CreateLocked()
Return Value
Returns a new locked value set with the same values as the original value set. The locked value set disallows all write operations except setting data values for existing values, which provides performance benefits when the value set is used to transfer data to or from tables or other objects.
Notes
The returned value set has all data values reset to null references.
Attempting to create a copy of a locked value set using ValueSet.CreateCopy creates an unlocked value set.
Attempting to create another locked copy of a locked value set using ValueSet.CreateLocked is equivalent to attempting to create a locked copy of the equivalent unlocked value set.
Locked value sets improve the performance of the following methods:
-
Command.Run - values,
-
Database.Run - values,
-
Database.RunCompile - values,
-
Table.Delete - keys,
-
Table.Insert - values,
-
Table.InsertCaptureKeys - values (keys can not be locked),
-
Table.Search - keys,
-
Table.SearchBatch - keys,
-
Table.SearchBatchBTree - keys,
-
Table.SearchBatchRTree - keys,
-
Table.Update - keys and values.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; using (Manifold.Table table = app.CreateTable()) { // change schema Manifold.Schema schema = table.GetSchema(); schema.AddField("a", "int32"); schema.AddField("b", "int32"); schema.AddField("c", "int32"); schema.AddField("d", "int32"); table.Design(schema); int records = 50000; // insert records using unlocked value set Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); values.AddValue("b"); values.AddValue("c"); values.AddValue("d"); System.DateTime tick1 = System.DateTime.Now; for (int index = 0; index < records; ++index) { values[0].Data = index; values[1].Data = index + 1000000; values[2].Data = index + 2000000; values[3].Data = index + 3000000; table.Insert(values); } System.DateTime tick2 = System.DateTime.Now; app.Log(string.Format("Unlocked value set: {0} records in {1} msec", records, (tick2 - tick1).Milliseconds)); // clear table table.DeleteAll(); // insert records using locked value set values = values.CreateLocked(); System.DateTime tick3 = System.DateTime.Now; for (int index = 0; index < records; ++index) { values[0].Data = index; values[1].Data = index + 1000000; values[2].Data = index + 2000000; values[3].Data = index + 3000000; table.Insert(values); } System.DateTime tick4 = System.DateTime.Now; app.Log(string.Format("Locked value set: {0} records in {1} msec", records, (tick4 - tick3).Milliseconds)); } app.OpenLog(); } // result: Unlocked value set: 50000 records in 493 msec // ....... Locked value set: 50000 records in 327 msec
The above example creates a new temporary table, inserts a big batch of records into it using an unlocked value set and then a locked value set and reports the time it took to insert records in each case.
49.8. ValueSet.DeleteValue
Syntax
void DeleteValue(string name)
Parameters
name - name of the value to delete. Case-insensitive.
Notes
The method deletes the value with the specified name. If the value with the specified name does not exist, the method will fail.
If the value set is locked, the method will fail.
To add a new value, use ValueSet.AddValue or ValueSet.AddValueType. To delete all values, use ValueSet.Clear. To determine the index of the value with the specified name, use ValueSet.FindValue. To check if the value with the specified name exists, use ValueSet.HasValue.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); values.AddValue("b"); values.AddValue("c"); values.DeleteValue("a"); foreach (Manifold.Value value in values) app.Log(value.Name); app.OpenLog(); } // result: b // ....... c
The above example creates a value set, fills it with example values, then deletes a value and reports the name of each remaining value.
49.9. ValueSet.FindValue
Syntax
int FindValue(string name)
Parameters
name - name of the value to locate. Case-insensitive.
Return Value
Returns the index of the value with the specified name. Returns a negative value if the value with the specified name does not exist.
Notes
The method locates a value with the specified name.
To add a new value, use ValueSet.AddValue or ValueSet.AddValueType. To delete a value, use ValueSet.DeleteValue. To delete all values, use ValueSet.Clear. To check if the value with the specified name exists, use ValueSet.HasValue.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); values.AddValue("b"); values.AddValue("c"); app.Log(string.Format("c : {0}", values.FindValue("c"))); app.Log(string.Format("d : {0}", values.FindValue("d"))); app.OpenLog(); } // result: c : 2 // ....... d : -1
The above example creates a value set, fills it with example values, then tries to locate several values and reports the result.
49.10. ValueSet.GetValueNames
Syntax
string[] GetValueNames()
Return Value
Returns names of all values.
Notes
Each call to the method returns a new object.
If the value set is empty, the method returns a null reference.
To add a new value, use ValueSet.AddValue or ValueSet.AddValueType. To delete a value, use ValueSet.DeleteValue. To delete all values, use ValueSet.Clear. To determine the index of the value with the specified name, use ValueSet.FindValue. To check if the value with the specified name exists, use ValueSet.HasValue.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); values.AddValue("b"); values.AddValue("c"); foreach (string name in values.GetValueNames()) app.Log(name); app.OpenLog(); } // result: a // ....... b // ....... c
The above example creates a value set, fills it with example values, then reports the name of each value.
49.11. ValueSet.HasValue
Syntax
bool HasValue(string name)
Parameters
name - name of the value to locate. Case-insensitive.
Return Value
Returns true if the value with the specified name exists, otherwise returns false.
Notes
The method locates a value with the specified name.
To add a new value, use ValueSet.AddValue or ValueSet.AddValueType. To delete a value, use ValueSet.DeleteValue. To delete all values, use ValueSet.Clear. To determine the index of the value with the specified name, use ValueSet.FindValue.
Examples
static Manifold.Context Manifold; static void Main() { Manifold.Application app = Manifold.Application; Manifold.ValueSet values = app.CreateValueSet(); values.AddValue("a"); values.AddValue("b"); values.AddValue("c"); app.Log(string.Format("c : {0}", values.HasValue("c")? "found": "not found")); app.Log(string.Format("d : {0}", values.HasValue("d")? "found": "not found")); app.OpenLog(); } // result: c : found // ....... d : not found
The above example creates a value set, fills it with example values, then tries to locate several values and reports the result.