# SQL Query

When a CAD drawing is opened in geometry render mode, the server converts CAD data to spatial data and stores it in a spatial database. You can run custom sql queries against this data from the frontend.

# Backend Table Structure

See Server-side conditional query and expression query for details.

For the backend table structure, use the condition part of the SQL statement for queries. You only need to write the part after where.

Table structure:

Field Name Type Description
id integer id
objectid text Entity id (block objectid: block id_referenced block def id1_referenced block def id2_entity id; group objectid: group id$entity id_element index; table: table id@entity id_element index; others: id_element index)
layerindex integer Layer index
name text Entity type value, e.g. "1" for AcDbLine; see "Supported CAD entity types" below
color int Color (from RGB, e.g. black 0x000000; with alpha 0xFF000000, unsigned 0xff000000<<0 = -16777216)
data blob Geometry data
s1 text Linetype
s2 text Extended dictionary data
s3 text Coordinate data; format varies by entity
s4 text String attribute data; format varies by entity
s5 text String attribute data; format varies by entity
n1 float Color index
n2 float Linetype scale
n3 float Line width
n4 float Transparency
n5 float Numeric attribute; format varies by entity
n6 float Numeric attribute; format varies by entity
n7 float Numeric attribute; format varies by entity
n8 float Numeric attribute; format varies by entity
n9 float Numeric attribute; format varies by entity
n10 float Numeric attribute; format varies by entity
geom GEOMETRY Entity bounding box

# Table Structure and Field Meanings

id objectid layerindex name color s3 s4 s5 n5 n6 n7 n8 n9 n10
DB id int Entity id text Layer index int Type value text Color int text text text numeric numeric numeric numeric numeric numeric
1 (AcDbLine) points thickness length
2 (AcDbPolyline) points bulge data3d area isclosed linetypeScale thickness elevation
3 (AcDb2dPolyline) points area isclosed polyType thickness elevation
4 (AcDb3dPolyline) points area isclosed polyType
5 (AcDbSpline) points area isclosed isFit fitTol degree
6 (AcDbArc) center area isclosed radius startAngle endAngle thickness
7 (AcDbCircle) center area isclosed radius thickness
8 (AcDbEllipse) center majorAxis area isclosed radius startAngle endAngle
9 (AcDbCurve) area isclosed
10 (AcDbBlockReference) positon attributeDef blockname rotate scaleX scaleY scaleZ
11 (AcDbHatch) points patternName elevation patternAngle patternScale
12 (AcDbMText) location contents text height width rotate textHeight actualHeight actualWidth
13 (AcDbText) location text height rotate horzMode
14 (AcDbShape) positon normal rotate size
15 (AcDbRasterImage) origin
16 (AcDbWipeout) 16
17 (AcDb2LineAngularDimension)
18 (AcDb3PointAngularDimension)
19 (AcDbAlignedDimension)
20 (AcDbArcDimension)
21 (AcDbDiametricDimension)
22 (AcDbOrdinateDimension)
23 (AcDbRadialDimension)
24 (AcDbRadialDimensionLarge)
25 (AcDbRotatedDimension)
26 (AcDbAttributeDefinition) location text contents height rotate horzMode
27 (AcDbAttribute) location text contents height rotate horzMode
28 (AcDbTable) positon attributeDef contents rotate scaleX scaleY scaleZ
29 (AcDbMLeader) location contents text height width rotate textHeight actualHeight actualWidth
30 (AcDbRegion) points indices data3d area perimeter
31 (AcDbPolyFaceMesh) points indices data3d
32 (AcDbPolygonMesh) points indices data3d
33 (AcDbSurface) points indices data3d
34 (AcDb3dSolid) points indices data3d
35 (AcDbFace) points indices data3d

# SQL Examples

Write only the part after where

Query all lines in the map:

name='1'
1

Query all 3D polylines on layer index 0:

name='4' and layerindex=0
1

Query red single-line text:

name='13' and color=-16776961
1

Query entity with objectid 9BE:

objectid='9BE'
1

Query all text (single-line, multi-line, attribute definition, block attribute):

name='13' or name='12' or name='26' or name='27'
1

Query block entities whose objectId starts with EA, 10D, or 19A:

objectid like 'EA_%'  or objectid like '10D_%'  or objectid like '19A_%'  
1

Query lines with length 10:

name='1' and n6 = 10
1

Query circles with radius 5:

name='7' and n7 = 5
1

# Conditional Query

 /**
 * Conditional query for entities
 * @param param Parameters
 * @param cb Callback for each point in result; if returns null, default handling is used
 */
conditionQueryFeature(param: IConditionQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any>;
/**
 * Conditional query parameters
 */
export  interface IConditionQueryFeatures extends IQueryBaseFeatures {
    /** Condition. */
    condition: string;
    /** Bounds or point coordinate array */
    bounds?: [number, number, number, number] | [number, number][];
    /** Get intersections when bounds is point array; default false */
    isGetIntersections?: boolean;
    /** Record start position. */
    beginpos?: number;
    /** Return geometry; for performance, when realgeom is false and count > 1, only bounding box per entity; when count is 1, returns real GeoJSON; when realgeom is true, returns GeoJSON per entity */
    includegeom?: boolean;
    /** Return real entity geometry GeoJSON. Used with includegeom. See includegeom. */
    realgeom?: boolean;
    /** Contain vs intersect; true = contain, false = intersect; default false (when bounds is provided for range query) */
    isContains?: boolean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Example: Query all text in the map

let query = await svc.conditionQueryFeature({
    condition: `name='13' or name='12' or name='26' or name='27'`, // Write only the condition after where; see "Server-side conditional query and expression query" for fields
    fields: "",
    geom: true,
    limit: 100000 // Large value to get all circles; default 100 if omitted
})
1
2
3
4
5
6
显示代码
全屏显示


# Point Query

 /**
 * Point query for entities
 * @param param Parameters
 * @param cb Callback for each point in result; if returns null, default handling is used
 */
pointQueryFeature(param: IPointQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any>;
  
/**
 * Point query parameters
 */
export  interface IPointQueryFeatures extends IQueryBaseFeatures {
    /** Query X coordinate. */
    x: number;
    /** Query Y coordinate. */
    y: number;
    /** Pixel size. */
    pixelsize?: number;
    /** Condition. */
    condition?: string;
    /** Max geometry bytes. */
    maxGeomBytesSize?: number;
    /** Geo length per pixel; if set, overrides zoom-based calculation. */
    pixelToGeoLength?: number;
}

/**
 * Query parameters
 */
export  interface IQueryBaseFeatures {
    /** Current zoom level. */
    zoom?: number;
    /** Map ID (empty = current open map). */
    mapid?: string;
    /** Map version (empty = current open version). */
    version?: string;
    /** Layer name (empty = current open map layer). */
    layer?: string;
    /** Max records. */
    limit?: number;
    /** Field list, comma-separated, e.g. "name,objectid" */
    fields?: string;
    /** Include geometry. */
    geom?: boolean;
    /** GeoJSON simplify tolerance in Mercator distance; default 0. E.g. for ~1px error at zoom 10: map.pixelToGeoLength(1, 10) * vjmap.Projection.EQUATORIAL_SEMIPERIMETER * 2 / map.getGeoBounds(1.0).width() */
    simplifyTolerance?: boolean;
    /** Enable cache (for memory-opened maps). */
    useCache?: boolean;
    /** Query returns Mercator by default; toMapCoordinate=true returns CAD map coordinates. */
    toMapCoordinate?: boolean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

Example Click to select CAD entity on overlay map (opens new window)

# Rectangle Query

 /**
 * Rectangle query for entities
 * @param param Parameters
 * @param cb Callback for each point in result; if returns null, default handling is used
 */
rectQueryFeature(param: IRectQueryFeatures, cb?: (point: [number, number]) => [number, number] | null | undefined): Promise<any>;
   

/**
 * Rectangle query parameters
 */
export  interface IRectQueryFeatures extends IQueryBaseFeatures {
    /** Query X1. (If x1,y1,x2,y2 all omitted, queries full map extent) */
    x1?: number;
    /** Query Y1. */
    y1?: number;
    /** Query X2. */
    x2?: number;
    /** Query Y2. */
    y2?: number;
    /** Condition. */
    condition?: string;
    /** Max geometry bytes. */
    maxGeomBytesSize?: number;
}

/**
 * Query parameters
 */
export  interface IQueryBaseFeatures {
    /** Current zoom level. */
    zoom?: number;
    /** Map ID (empty = current open map). */
    mapid?: string;
    /** Map version (empty = current open version). */
    version?: string;
    /** Layer name (empty = current open map layer). */
    layer?: string;
    /** Max records. */
    limit?: number;
    /** Field list, comma-separated, e.g. "name,objectid" */
    fields?: string;
    /** Include geometry. */
    geom?: boolean;
    /** GeoJSON simplify tolerance in Mercator distance; default 0. E.g. for ~1px error at zoom 10: map.pixelToGeoLength(1, 10) * vjmap.Projection.EQUATORIAL_SEMIPERIMETER * 2 / map.getGeoBounds(1.0).width() */
    simplifyTolerance?: boolean;
    /** Enable cache (for memory-opened maps). */
    useCache?: boolean;
    /** Query returns Mercator by default; toMapCoordinate=true returns CAD map coordinates. */
    toMapCoordinate?: boolean;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

Example Auto-generate CAD engineering section from data (opens new window)

For rectangle query, you can also use conditionQueryFeature with bounds set to a rectangle [number, number, number, number].

# Polygon Query

Use conditionQueryFeature for polygon query with bounds set to a coordinate array Array<[number, number]>.

Example Polygon select entities (opens new window)

# Paginated Query

Use paginated query when there is a lot of data.

Example: Query all line segments (lines, 2D/3D polylines) in the map

 // Find all line segments in map
const  getMapHVLines = async () => {
    // Find all lines, 2D/3D polylines
    let queryEntTypes = ['AcDbLine', 'AcDbPolyline', 'AcDb2dPolyline', 'AcDb3dPolyline'];
    let cond = queryEntTypes.map(t => `name='${getTypeNameById(t)}'`).join(' or '); // SQL condition

    let result = [];
    let beginPos = 0; // Query start position
    // Use paginated query for large datasets
    while(true) {
        let query = await svc.conditionQueryFeature({
            condition: cond, // Write only the condition after where; see "Server-side conditional query and expression query" for fields
            fields: "objectid,points,envelop", // Only id and coordinates
            beginpos: beginPos, // Start position
            limit: 100000 // 100k per batch
        });
        beginPos += query.result.length; // Advance start position
        result.push(...query.result || []);
        if (result.length >= query.recordCount) break;
    }

    result = result.filter(e => {
        let points = e.points.split(";");
        if (points.length !=2 ) return false;
        e.geoStart = vjmap.GeoPoint.fromString(points[0]);
        delete e.geoStart.z;// Ignore z
        e.geoEnd = vjmap.GeoPoint.fromString(points[1]);
        delete e.geoEnd.z;// Ignore z

        if (e.geoStart.x > e.geoStart.x) {
            // Swap
            let temp = e.geoStart;
            e.geoStart = e.geoEnd;
            e.geoEnd = temp;
        }
        e.startPoint = e.geoStart.toString();
        e.endPoint =  e.geoEnd.toString();
        if (e.startPoint == e.endPoint) {
            // Same point
            return false;
        }
        let line = points.map(e=>vjmap.geoPoint(e.split(",")))
        let isVLine = vjmap.isZero(line[0].x - line[1].x);// Vertical
        let isHLine = vjmap.isZero(line[0].y - line[1].y);// Horizontal
        if (!(isVLine || isHLine)) return false; // Must be horizontal or vertical

        e.isHorzLine = isHLine;
        return true
    })
    return result;
}
// Entity type ID to name mapping
const { entTypeIdMap } = await svc.getConstData();
const getTypeNameById = name => {
    for(let id in entTypeIdMap) {
        if (entTypeIdMap[id] == name) {
            return id
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60