Digamos que creamos la clase persistente Point:
<span class="hljs-keyword">Class</span> <span class="hljs-keyword">try</span>.Point <span class="hljs-keyword">Extends</span> <span class="hljs-built_in">%Persistent</span> [DDLAllowed]
{
<span class="hljs-keyword">Property</span> <span class="hljs-keyword">X</span><span class="hljs-comment">;</span>
<span class="hljs-keyword">Property</span> Y<span class="hljs-comment">;</span>
}
Podríamos igualmente utilizar este DDL para crearla:
CREATE <span class="hljs-keyword">Table</span> try.Point <span class="hljs-comment">(
X VARCHAR(50),
Y VARCHAR(50))</span>
Y se crearía la misma clase.
Después de la compilación, nuestra nueva clase debería tener una estructura Storage autogenerada que define el mapeo de globals a los datos en las columnas o propiedades:
Storage Default
{
<span class="hljs-tag"><<span class="hljs-name">Data</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"PointDefaultData"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Value</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"1"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Value</span>></span>%%CLASSNAME<span class="hljs-tag"></<span class="hljs-name">Value</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Value</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Value</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"2"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Value</span>></span>X<span class="hljs-tag"></<span class="hljs-name">Value</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Value</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Value</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"3"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Value</span>></span>Y<span class="hljs-tag"></<span class="hljs-name">Value</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Value</span>></span>
<span class="hljs-tag"></<span class="hljs-name">Data</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DataLocation</span>></span>^try.PointD<span class="hljs-tag"></<span class="hljs-name">DataLocation</span>></span>
<span class="hljs-tag"><<span class="hljs-name">DefaultData</span>></span>PointDefaultData<span class="hljs-tag"></<span class="hljs-name">DefaultData</span>></span>
<span class="hljs-tag"><<span class="hljs-name">IdLocation</span>></span>^try.PointD<span class="hljs-tag"></<span class="hljs-name">IdLocation</span>></span>
<span class="hljs-tag"><<span class="hljs-name">IndexLocation</span>></span>^try.PointI<span class="hljs-tag"></<span class="hljs-name">IndexLocation</span>></span>
<span class="hljs-tag"><<span class="hljs-name">StreamLocation</span>></span>^try.PointS<span class="hljs-tag"></<span class="hljs-name">StreamLocation</span>></span>
<span class="hljs-tag"><<span class="hljs-name">Type</span>></span>%Library.CacheStorage<span class="hljs-tag"></<span class="hljs-name">Type</span>></span>
}
¿Qué está pasando aquí?
Desde abajo hacia arriba (en negrita está lo importante, puedes ignorar el resto por ahora):
-
Type: tipo de almacenamiento generado. Een nuestro caso este es el tipo de almacenamiento por defecto para las clases persistentes
-
StreamLocation - nombre del global donde se almacenan los Streams
-
IndexLocation - nombre del global donde se almacenan los índices
-
IdLocation - nombre del global donde almacenamos el contador del ID autoincremental
-
DefaultData - nombre del elemento de almacenamiento XML que define el mapeo entre las columnas/propiedades y el global
-
DataLocation - nombre del global donde almacenamos los datos
En este momento nuestro DefaulData es PointDefaultData, así que vamos a verlo. En esencia nos dice qué nodo del global almacena qué valor, con la siguiente estructura:
-
1 - %%CLASSNAME
-
2 - X
-
3 - Y
De forma que podemos esperar que nuestro global tenga esta pinta:
^<span class="hljs-keyword">try</span>.PointD(<span class="hljs-built_in">id</span>) = %%CLASSNAME, X, Y
Si sacamos por pantalla el valor del global, inicialmente estará vacío, porque no hemos añadido ningún dato:
<span class="hljs-keyword">zw</span> <span class="hljs-symbol">^try</span>.PointD
Vamos a añadir un objeto:
<span class="hljs-keyword">set</span> p = <span class="hljs-keyword">##class</span>(<span class="hljs-keyword">try</span>.Point).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> p.<span class="hljs-keyword">X</span> = <span class="hljs-number">1</span>
<span class="hljs-keyword">set</span> p.Y = <span class="hljs-number">2</span>
<span class="hljs-keyword">write</span> p.<span class="hljs-built_in">%Save</span>()
Revisamos el global de nuevo y ¿qué tenemos?
<span class="hljs-keyword">zw</span> <span class="hljs-symbol">^try</span>.PointD
<span class="hljs-symbol">^try</span>.PointD=<span class="hljs-number">1</span>
<span class="hljs-symbol">^try</span>.PointD(<span class="hljs-number">1</span>)=<span class="hljs-built_in">$lb</span>(<span class="hljs-string">""</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)
Como puedes ver, nuestra estructura esperada (%%CLASSNAME, X, Y) está establecida con $lb("",1,2), que corresponde a las propiedades X e Y de nuestro objeto (%%CLASSNAME es una propiedad del sistema, podemos ignorarla por ahora).
Podemos igualmente añadir una nueva fila mediante SQL:
<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> try.Point (X, Y) <span class="hljs-keyword">VALUES</span> (<span class="hljs-number">3</span>,<span class="hljs-number">4</span>)
Ahora nuestro global tiene esta pinta:
<span class="hljs-keyword">zw</span> <span class="hljs-symbol">^try</span>.PointD
<span class="hljs-symbol">^try</span>.PointD=<span class="hljs-number">2</span>
<span class="hljs-symbol">^try</span>.PointD(<span class="hljs-number">1</span>)=<span class="hljs-built_in">$lb</span>(<span class="hljs-string">""</span>,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>)
<span class="hljs-symbol">^try</span>.PointD(<span class="hljs-number">2</span>)=<span class="hljs-built_in">$lb</span>(<span class="hljs-string">""</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>)
De esta forma, siempre que añadimos datos vía objetos o SQL, éstos son almacenados de acuerdo a la definición del Storage (eEs posible modificar manualmente la definición del Storage - puedes probar tú mismo y ver qué pasa).
Ahora bien, ¿qué pasa cuando queremos ejecutar una consulta SQL?
<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">try</span>.Point
Esta consulta se traduce en código ObjectScript, que itera sobre el global definido y puebla las columnas en base a la definición del Storage.
Ahora vamos a por las modificaciones. Borremos todos los datos de la tabla.
<span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">FROM</span> <span class="hljs-keyword">try</span>.Point
Veamos el global después de esto:
<span class="hljs-keyword">zw</span> <span class="hljs-symbol">^try</span>.PointD
<span class="hljs-symbol">^try</span>.PointD=<span class="hljs-number">2</span>
Fijaos que solo el contador del ID se mantiene, de esta forma el siguiente nuevo objeto/fila tendrá el ID=3. Nuestra clase y tabla continúa existiendo.
Pero ¿qué pasa si hacemos?:
DROP <span class="hljs-keyword">TABLE</span> try.Point
Esto destruye nuestra tabla, clase y borra todo el global.
<span class="hljs-keyword">zw</span> <span class="hljs-symbol">^try</span>.PointD
Espero que siguiendo este ejemplo ahora entiendas mejor cómo los globals, las clases y las tablas se corresponden unos con otros.
Podríamos igualmente utilizar este DDL para crearla:
Y se crearía la misma clase.
Después de la compilación, nuestra nueva clase debería tener una estructura Storage autogenerada que define el mapeo de globals a los datos en las columnas o propiedades:
¿Qué está pasando aquí?
Desde abajo hacia arriba (en negrita está lo importante, puedes ignorar el resto por ahora):
En este momento nuestro DefaulData es PointDefaultData, así que vamos a verlo. En esencia nos dice qué nodo del global almacena qué valor, con la siguiente estructura:
De forma que podemos esperar que nuestro global tenga esta pinta:
Si sacamos por pantalla el valor del global, inicialmente estará vacío, porque no hemos añadido ningún dato:
Vamos a añadir un objeto:
Revisamos el global de nuevo y ¿qué tenemos?
Como puedes ver, nuestra estructura esperada (%%CLASSNAME, X, Y) está establecida con $lb("",1,2), que corresponde a las propiedades X e Y de nuestro objeto (%%CLASSNAME es una propiedad del sistema, podemos ignorarla por ahora).
Podemos igualmente añadir una nueva fila mediante SQL:
Ahora nuestro global tiene esta pinta:
De esta forma, siempre que añadimos datos vía objetos o SQL, éstos son almacenados de acuerdo a la definición del Storage (eEs posible modificar manualmente la definición del Storage - puedes probar tú mismo y ver qué pasa).
Ahora bien, ¿qué pasa cuando queremos ejecutar una consulta SQL?
Esta consulta se traduce en código ObjectScript, que itera sobre el global definido y puebla las columnas en base a la definición del Storage.
Ahora vamos a por las modificaciones. Borremos todos los datos de la tabla.
Veamos el global después de esto:
Fijaos que solo el contador del ID se mantiene, de esta forma el siguiente nuevo objeto/fila tendrá el ID=3. Nuestra clase y tabla continúa existiendo.
Pero ¿qué pasa si hacemos?:
Esto destruye nuestra tabla, clase y borra todo el global.
Espero que siguiendo este ejemplo ahora entiendas mejor cómo los globals, las clases y las tablas se corresponden unos con otros.