Manifold APIs

All APIs - Object model for .NET / COM

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:

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:

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:

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

C# VBScript IronPython
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.

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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:

An rtree index supports the following combinations of fields:

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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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:

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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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.

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
// 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:

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

C# VBScript IronPython
// 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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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.

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

C# VBScript IronPython
// 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.

C# VBScript IronPython
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.

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
// 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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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.

C# VBScript IronPython
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.

C# VBScript IronPython
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.

C# VBScript IronPython
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

C# VBScript IronPython
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

C# IronPython
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

C# IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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:

Examples

C# VBScript IronPython
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

C# VBScript IronPython
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

C# VBScript IronPython
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

C# IronPython
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

C# VBScript IronPython
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.