Собственные типы индексов в СУБД caché

Post on 15-Apr-2017

102 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Собственные типы индексов (они же функциональные индексы)

Конечный результат

Property A As %String;

Property B As %String;

Index someind On (A,B) As CustomPackage.CustomIndex;

Собственно квадродерево

Class SpatialIndex.Indexer {

Method %OnNew(indexGlobal As %String) As %Status

Method Insert(x As %Float, y As %Float, id As %String)

Method Delete(x As %Float, y As %Float, id As %String)

}

ClassMethod InsertIndex(pID, pArg... As %Binary) [ CodeMode = generator] {

if %mode'="method" {

set IndexGlobal = ..IndexLocation(%class,%property)

$$$GENERATE($C(9)_"set indexer = " _

"##class(SpatialIndex.Indexer).%New($Name("_IndexGlobal_"))")

$$$GENERATE($C(9)_"do indexer.Insert(pArg(1),pArg(2),pID)")

}

}

Class SpatialIndex.Index Extends %Library.FunctionalIndex

Пример использования

Class SpatialIndex.Test Extends %Persistent {

Property Name As %String(MAXLEN = 300);

Property Latitude As %String;

Property Longitude As %String;

Index coord On (Latitude, Longitude) As SpatialIndex.Index;

}

SpatialIndex.Test.1.INT

zcoordInsertIndex(pID,pArg...) public {

set indexer =

##class(SpatialIndex.Indexer).%New($Name(^SpatialIndex.TestI("coord")))

do indexer.Insert(pArg(1),pArg(2),pID)

}

zcoordUpdateIndex(pID,pArg...) public {

set indexer =

##class(SpatialIndex.Indexer).%New($Name(^SpatialIndex.TestI("coord")))

do indexer.Delete(pArg(3),pArg(4),pID)

do indexer.Insert(pArg(1),pArg(2),pID)

}

SpatialIndex.Test.1.INT

%SaveData(id) {

if insert {

// ...

do ..coordInsertIndex(id,i%Latitude,i%Longitude,"")

// ...

} else {

// ...

do ..coordUpdateIndex(id,i%Latitude,i%Longitude,zzc27v3,zzc27v2,"")

// ...

}

}

Так данные индекса выглядят в глобале

USER>zwrite ^SpatialIndex.TestI("coord")

^SpatialIndex.TestI("coord"," ")=$lb(-180,-90,180.0001,90.0001,0,0)

...

^SpatialIndex.TestI("coord"," 30")=$lb(.00005,.00005,90.000075,45.000075,0,0)

^SpatialIndex.TestI("coord"," 300")=$lb(.00005,.00005,45.0000625,22.5000625,1,0)

^SpatialIndex.TestI("coord"," 301")=$lb(45.0000625,.00005,90.000075,22.5000625,0,0)

^SpatialIndex.TestI("coord"," 3010")=$lb(45.0000625,.00005,67.50006875,11.25005625,1,0)

^SpatialIndex.TestI("coord"," 3011")=$lb(67.50006875,.00005,90.000075,11.25005625,1,0)

^SpatialIndex.TestI("coord"," 3012")=$lb(45.0000625,11.25005625,67.50006875,22.5000625,0,0)

^SpatialIndex.TestI("coord"," 30120")=$lb(45.0000625,11.25005625,56.250065625,16.875059375,1,0)

...

А как же запросы?

SELECT *

FROM SpatialIndex.Test

WHERE %ID %FIND search_index(coord, 'window',

'minx=56,miny=56,maxx=57,maxy=57')

Снова SpatialIndex.Indexer

ClassMethod Find(queryType As %Binary, queryParams As %String) As

%Library.Binary [ CodeMode = generator, SqlProc ]

{

if %mode'="method" {

set IndexGlobal = ..IndexLocation(%class,%property)

$$$GENERATE($C(9)_"set result = ##class(SpatialIndex.SQLResult).%New()")

$$$GENERATE($C(9)_"do result.PrepareFind($Name("_IndexGlobal_"),

queryType, queryParams)")

$$$GENERATE($C(9)_"quit result")

}

}

search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')

Метод, сгенерированный в SpatialIndex.Test.1.INT

zcoordFind(queryType,queryParams) public { Set:'$isobject($get(%sqlcontext)) %sqlcontext=##class(%Library.ProcedureContext).%New()

set result = ##class(SpatialIndex.SQLResult).%New()

do result.PrepareFind($Name(^SpatialIndex.TestI("coord")), queryType,

queryParams)

quit result }

search_index(coord, 'window', 'minx=56,miny=56,maxx=57,maxy=57')

Class SpatialIndex.SQLResult Extends %SQL.AbstractFind

Property ResultBits [ MultiDimensional, Private ];

Method PrepareFind(indexGlobal As %String, queryType As %String, queryParams As %Binary) As %Status { // … }

Method NextChunk(ByRef pChunk As %Integer = "") As %Binary { set pChunk = $order(i%ResultBits(pChunk),1,tBits) quit:pChunk="" "" quit tBits }

Method ContainsItem(pItem As %String) As %Boolean { set tChunk = (pItem\64000)+1, tPos=(pItem#64000)+1 quit $bit($get(i%ResultBits(tChunk)),tPos) }

В итоге запросы выглядят так:

SELECT *

FROM SpatialIndex.Test

WHERE %ID %FIND search_index(coord,'radius','x=55,y=55,radiusX=2,radiusY=2') and name %StartsWith 'Z'

Параметр size предиката %FIND

SELECT *

FROM SpatialIndex.Test

WHERE name %startswith 'za'

and %ID %FIND

search_index(coord,'radius','x=55,y=55,radius=2')

size ((10))

Спасибо. Вопросы?

http://habrahabr.ru/company/intersystems/blog/272689/

top related