| |
| /pliant/storage/database/prototype.pli |
| |
| 1 |
abstract | |
| 2 |
[Pliant database engine is based on an abstract interface (a set of generic methods) used to access real datas which type is not known by the application that access them. ] ; eol | |
| 3 |
[This module defines the interface methods.] | |
| 4 |
| |
| 5 |
# Copyright Hubert Tonneau hubert.tonneau@pliant.cx | |
| 6 |
# | |
| 7 |
# This program is free software; you can redistribute it and/or | |
| 8 |
# modify it under the terms of the GNU General Public License version 2 | |
| 9 |
# as published by the Free Software Foundation. | |
| 10 |
# | |
| 11 |
# This program is distributed in the hope that it will be useful, | |
| 12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 |
# GNU General Public License for more details. | |
| 15 |
# | |
| 16 |
# You should have received a copy of the GNU General Public License | |
| 17 |
# version 2 along with this program; if not, write to the Free Software | |
| 18 |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 19 |
| |
| 20 |
module "/pliant/language/compiler.pli" | |
| 21 |
module "/pliant/language/data/string_cast.pli" | |
| 22 |
module "/pliant/util/encoding/html.pli" | |
| 23 |
| |
| 24 |
module "/pliant/language/compiler/type/inherit.pli" | |
| 25 |
module "/pliant/language/data/cache.pli" | |
| 26 |
module "/pliant/language/stream.pli" | |
| 27 |
| |
| 28 |
constant autocreate false | |
| 29 |
| |
| 30 |
public | |
| 31 |
| |
| 32 |
(gvar TraceSlot database_trace) configure "database" | |
| 33 |
| |
| 34 |
type DataInterface_ | |
| 35 |
void | |
| 36 |
| |
| 37 |
flagset DatabaseFlags | |
| 38 |
database_loading | |
| 39 |
database_modified | |
| 40 |
database_compressed | |
| 41 |
database_autoclose | |
| 42 |
database_autostore | |
| 43 |
| |
| 44 |
type Database_ | |
| 45 |
inherit CachePrototype | |
| 46 |
field Pointer:Sem sem | |
| 47 |
field Str path | |
| 48 |
field DatabaseFlags flags | |
| 49 |
| |
| 50 |
CachePrototype maybe Database_ | |
| 51 |
| |
| 52 |
type DataScanBuffer | |
| 53 |
field Int int | |
| 54 |
field Address adr | |
| 55 |
field Arrow arrow | |
| 56 |
| |
| 57 |
| |
| 58 |
| |
| 59 |
| |
| 60 |
doc | |
| 61 |
fixed [Data_ ] ; [is pointer to a data in the database.] ; eol | |
| 62 |
[It contains:] | |
| 63 |
list | |
| 64 |
item | |
| 65 |
[The address of the true data (but the true data type is unknown). See] ; fixed [ DataInterface_ ] ; [below.] | |
| 66 |
item [An arrow to the object that contains the data. This will prevent the data to be freed as long as we have a pointer to it.] | |
| 67 |
item [The interface that is an object that contains the generic methods that will be used to access the data.] | |
| 68 |
item [The base is the pointer to database the data belongs to.] | |
| 69 |
item [The data path (a string like a file path that identify the object and can be used to get an access to it) is stored in two parts for speed reasons.] | |
| 70 |
| |
| 71 |
| |
| 72 |
type Data_ | |
| 73 |
field Address adr | |
| 74 |
field Arrow object | |
| 75 |
field Link:DataInterface_ interface | |
| 76 |
field Link:Database_ base | |
| 77 |
field Link:Str path1 | |
| 78 |
field Pointer:Str path2 | |
| 79 |
| |
| 80 |
| |
| 81 |
gvar DataInterface_ empty_interface | |
| 82 |
gvar Database_ empty_database | |
| 83 |
gvar Sem empty_sem | |
| 84 |
empty_database sem :> empty_sem | |
| 85 |
gvar Str empty_string | |
| 86 |
| |
| 87 |
function build d | |
| 88 |
arg_w Data_ d | |
| 89 |
d adr := null | |
| 90 |
d interface :> empty_interface | |
| 91 |
d base :> empty_database | |
| 92 |
d path1 :> empty_string | |
| 93 |
d path2 :> null map Str | |
| 94 |
| |
| 95 |
gvar Data_ data_null | |
| 96 |
| |
| 97 |
method d key -> k | |
| 98 |
arg Data_ d ; arg Str k | |
| 99 |
if (exists d:path2) | |
| 100 |
k := html_decode (d:path2 1 d:path2:len) | |
| 101 |
else | |
| 102 |
var Int i := d:path1 search_last "/" -1 | |
| 103 |
k := html_decode (d:path1 i+1 d:path1:len) | |
| 104 |
| |
| 105 |
method d dbpath -> p | |
| 106 |
arg Data_ d ; arg Str p | |
| 107 |
if (exists d:path2) | |
| 108 |
p := d:path1+d:path2 | |
| 109 |
else | |
| 110 |
p := d:path1 | |
| 111 |
| |
| 112 |
method d path -> p | |
| 113 |
arg Data_ d ; arg Str p | |
| 114 |
if (exists d:path2) | |
| 115 |
p := d:base:path+d:path1+d:path2 | |
| 116 |
else | |
| 117 |
p := d:base:path+d:path1 | |
| 118 |
| |
| 119 |
| |
| 120 |
| |
| 121 |
| |
| 122 |
doc | |
| 123 |
[The data that pointed by] ; fixed [ Data_ ] ; [is of an unknown real type, so we must use generic methods to access it. ] | |
| 124 |
[Also the data pointed is not always a true object (a field in a record is not, for memory compactness reasons), so instead od calling the generic method on the data directely, we use the link to the] ; fixed [ DataInterace_ ] ; [object which is stored in the] ; fixed [ Data_ ] ; [pointer, and call the generic method in this one.] ; eol | |
| 125 |
[You could see the] ; fixed [ DataInterface_ ] ; [as a functions array.] | |
| 126 |
| |
| 127 |
| |
| 128 |
method di type d -> t | |
| 129 |
oarg DataInterface_ di ; arg Data_ d ; arg_R Type t | |
| 130 |
generic | |
| 131 |
# get the physical type of the data associated with this node | |
| 132 |
t :> Void | |
| 133 |
| |
| 134 |
method di get d adr type -> status | |
| 135 |
oarg DataInterface_ di ; arg Data_ d ; arg Address adr ; arg Type type ; arg Status status | |
| 136 |
generic | |
| 137 |
# try to read the data associated with this node, and cast it to the specify type | |
| 138 |
status := failure | |
| 139 |
# | |
| 140 |
# the following seems to be both buggy (using 'object' instead of 'adr') and of no use, | |
| 141 |
# I just comment it out since I can't remember why I wrote it, so it might be of some use anyway. | |
| 142 |
# | |
| 143 |
# if d:object<>null | |
| 144 |
# if type=(entry_type d:object) | |
| 145 |
# type copy_instance d:object adr | |
| 146 |
# else | |
| 147 |
# var Str s := to_string d:object (entry_type d:object) "db" | |
| 148 |
# from_string adr type s "db" | |
| 149 |
| |
| 150 |
method di set d adr type -> status | |
| 151 |
oarg_rw DataInterface_ di ; arg_rw Data_ d ; arg Address adr ; arg Type type ; arg Status status | |
| 152 |
generic | |
| 153 |
# try to set the data associated with this node to the provided typed value | |
| 154 |
status := failure | |
| 155 |
| |
| 156 |
method di reset d -> status | |
| 157 |
oarg_rw DataInterface_ di ; arg_rw Data_ d ; arg Status status | |
| 158 |
generic | |
| 159 |
# resets the subtree starting at this node | |
| 160 |
status := failure | |
| 161 |
| |
| 162 |
| |
| 163 |
method di search d k -> d2 | |
| 164 |
oarg DataInterface_ di ; arg Data_ d ; arg Str k ; arg Data_ d2 | |
| 165 |
generic | |
| 166 |
# get a link to the node at the end of the edge with the provided name | |
| 167 |
d2 := data_null | |
| 168 |
d2 base :> d base | |
| 169 |
d2 path1 :> new Str d:dbpath+"/"+html_encode:k | |
| 170 |
d2 path2 :> null map Str | |
| 171 |
| |
| 172 |
| |
| 173 |
method di first d start stop buf -> d2 | |
| 174 |
oarg DataInterface_ di ; arg Data_ d ; arg Str start stop ; arg_w DataScanBuffer buf ; arg Data_ d2 | |
| 175 |
generic | |
| 176 |
# get a link to the first son in the tree which key is >=start and <stop | |
| 177 |
# (stop is ignore if it's len is zero) | |
| 178 |
# (returns data_null node if none is matching the constains) | |
| 179 |
d2 := data_null | |
| 180 |
| |
| 181 |
method di next d start stop buf -> d2 | |
| 182 |
oarg DataInterface_ di ; arg Data_ d ; arg Str start stop ; arg_rw DataScanBuffer buf ; arg Data_ d2 | |
| 183 |
generic | |
| 184 |
# get a link to the next son that still match the constains | |
| 185 |
| |
| 186 |
method di count d start stop -> count | |
| 187 |
oarg_rw DataInterface_ di ; arg Data_ d ; arg Str start stop ; arg Int count | |
| 188 |
generic | |
| 189 |
# get the number of sons that match the constains | |
| 190 |
count := 0 | |
| 191 |
| |
| 192 |
| |
| 193 |
method di create d k -> status | |
| 194 |
oarg_rw DataInterface_ di ; arg_rw Data_ d ; arg Str k ; arg Status status | |
| 195 |
generic | |
| 196 |
# creates a new node | |
| 197 |
status := failure | |
| 198 |
| |
| 199 |
method di delete d k -> status | |
| 200 |
oarg_rw DataInterface_ di ; arg_rw Data_ d ; arg Str k ; arg Status status | |
| 201 |
generic | |
| 202 |
# deletes the subtree starting at the node at the end of the edge with the provided name | |
| 203 |
status := failure | |
| 204 |
| |
| 205 |
| |
| 206 |
| |
| 207 |
| |
| 208 |
| |
| 209 |
method di search d k createit -> d2 | |
| 210 |
oarg_rw DataInterface_ di ; arg_rw Data_ d ; arg Str k ; arg CBool createit ; arg Data_ d2 | |
| 211 |
d2 := di search d k | |
| 212 |
if d2:adr=null and createit | |
| 213 |
if (di create d k)=success | |
| 214 |
d2 := di search d k | |
| 215 |
| |
| 216 |
| |
| 217 |
method di first_to_store d start stop buf -> d2 | |
| 218 |
oarg DataInterface_ di ; arg Data_ d ; arg Str start stop ; arg_w DataScanBuffer buf ; arg Data_ d2 | |
| 219 |
generic | |
| 220 |
d2 := di first d start stop buf | |
| 221 |
| |
| 222 |
method di next_to_store d start stop buf -> d2 | |
| 223 |
oarg DataInterface_ di ; arg Data_ d ; arg Str start stop ; arg_rw DataScanBuffer buf ; arg Data_ d2 | |
| 224 |
generic | |
| 225 |
d2 := di next d start stop buf | |
| 226 |
| |
| 227 |
| |
| 228 |
method di pre_delete d k | |
| 229 |
arg DataInterface_ di ; arg Data_ d ; arg Str k | |
| 230 |
generic | |
| 231 |
| |
| 232 |
| |
| 233 |
method di get_raw d adr type -> status | |
| 234 |
oarg DataInterface_ di ; arg Data_ d ; arg Address adr ; arg Type type ; arg Status status | |
| 235 |
generic | |
| 236 |
status := di get d adr type | |
| 237 |
| |
| 238 |
method di set_raw d adr type -> status | |
| 239 |
oarg_rw DataInterface_ di ; arg_rw Data_ d ; arg Address adr ; arg Type type ; arg Status status | |
| 240 |
generic | |
| 241 |
status := di set d adr type | |
| 242 |
| |
| 243 |
| |
| 244 |
| |
| 245 |
| |
| 246 |
doc | |
| 247 |
[The] ; fixed [ Database_ ] ; [type defines the generic methods that a] ; fixed [ Data_ ] ; [will use to notify the database that a data has been modifyed.] | |
| 248 |
| |
| 249 |
method db update stream -> status | |
| 250 |
oarg_rw Database_ db ; arg_rw Stream stream ; arg ExtendedStatus status | |
| 251 |
generic | |
| 252 |
status := failure "not implemented" | |
| 253 |
| |
| 254 |
method db dump stream -> status | |
| 255 |
oarg_rw Database_ db ; arg_rw Stream stream ; arg ExtendedStatus status | |
| 256 |
generic | |
| 257 |
status := failure "not implemented" | |
| 258 |
| |
| 259 |
method db sleep | |
| 260 |
oarg_rw Database_ db | |
| 261 |
generic | |
| 262 |
| |
| 263 |
method db drop | |
| 264 |
oarg_rw Database_ db | |
| 265 |
generic | |
| 266 |
| |
| 267 |
method db get_root d | |
| 268 |
arg Database_ db ; arg_w Data_ d | |
| 269 |
generic | |
| 270 |
d := data_null | |
| 271 |
| |
| 272 |
method db notify_set d adr type | |
| 273 |
arg_rw Database_ db ; arg Data_ d ; arg Address adr ; arg Type type | |
| 274 |
generic | |
| 275 |
| |
| 276 |
method db notify_reset d | |
| 277 |
arg_rw Database_ db ; arg Data_ d | |
| 278 |
generic | |
| 279 |
| |
| 280 |
method db notify_create d k | |
| 281 |
arg_rw Database_ db ; arg Data_ d ; arg Str k | |
| 282 |
generic | |
| 283 |
| |
| 284 |
method db notify_delete d k | |
| 285 |
arg_rw Database_ db ; arg Data_ d ; arg Str k | |
| 286 |
generic | |
| 287 |
| |
| 288 |
method db query command -> answer | |
| 289 |
oarg Database_ db ; arg Str command answer | |
| 290 |
generic | |
| 291 |
answer := "" | |
| 292 |
| |
| 293 |
method db configure command -> status | |
| 294 |
oarg_rw Database_ db ; arg Str command ; arg Status status | |
| 295 |
generic | |
| 296 |
status := failure | |
| |