Basic Database Data Techniques
Comparing Enumerator Values
This is something that may be documented somewhere, but I just never found it. If you get the value of a field of a record that is an enumerated value, the value is typically a string (more correctly, a ds_char16_vec [or some other stored character string]). If you need to test against that value you need to do an '=' test. And if you have translation functionality, you would need to do multiple tests or use a message handler. However there is another field that actually returns the integer value of the enumerator. It is named 'dsint!field_name'
In-memory Enumerators
You can create an in-memory enumerator on a field by creating 2 methods. This is typically wanted when you want to restrict values of a field, but do not want to deal with setting up an enumerator or a dynamic enumerator. You could also use this methodology to have the enumerated list be dependent on some other attribute or situation. Like only show only 2 potential values to basic users, and show all values to advanced users. First you need to set up the field you want as enumerated thru the case tool as a basic physical field. I've only played around with string type field. But maybe numbers also work also.
You need to create the following 2 methods:
_method the_rec_exemplar.can_match?(a_field_descriptor)
## returns boolean
## Return true if a_field_descriptor.name matches the field you want to enumerate
## otherwise return super.can_match?(a_field_descriptor)
_if a_field_descriptor.name _is :my_field
_then
_return _true
_endif
_return _super.can_match?(a_field_descriptor)
_endmethod
$
_method the_rec_exemplar.match_string(a_fd,a_string,_optional record)
## returns collection of potential values
## returns super.match_string() if not the field I'm interested in
# Actually I am a tad unsure exactly when this method should return something
# other than the full list
_if record _is _unset
_then
record << _self
_endif
_if a_fd.name _isnt :int!type
_then
_return _super.match_string(a_fd,a_string,record)
_endif
_return {"foo","bar","cat","dog"}
_endmethod
Temporary Database Storage
A little known feature with the versioned database is the ability to create a temporary alternative to store data. This very useful if you are doing a large amount of analysis that may cause your memory to exceed operating restrictions. Another option would be to cache things so you do not not need to recalculate the data many times (especially for drawing).
To create this temporary alternative, you use ds_version_view.create_scratchpad(). See the method comments for details, but one great thing about this functionality is that if you cleanly leave the alternative, all of the UVAs associated with this temporary alternative are returned to the system!
Quinn Hiebert at Fasterre has played with this and could provide more information on how he used it.
Scrapbook (Clipboard)
The Scrapbook from the Smallworld Explorer allows you to easily park record sets for future uses. Typically you will see utilities give you the option of using selected records or 'Scrapbook.' If there are processes that run on DS records (non geometry records) the only way of getting a handle on a select few is through the Scrapbook.
To set the Scrapbook use set_clipboard() on the scrapbook object like the following.
gis_program_manager.scrapbook().set_clipboard("test",{an_rwo_set})
To get data from the Scrapbook get the elements of each clipboard like the following. Note the data may be detached records….
_local recs << rwo_set.new()
_for aCB _over gis_program_manager.scrapbook().clipboard.fast_elements()
_loop
recs.add_all(aCB)
_endloop
Saving Current Scrapbook
You can save the current Scrapbook for future use even after session restart.
gis_program_manager.scrapbook().store("a_test")
Coordinate System Look Ups
Spatial Reference Coding
Below is some code that will look up coordinate systems based on code and optionally unit. Spatial Reference Website contains many ESRI & ESPG codes that are commonly used.
_pragma(classify_level=basic, topic={fcsi,coordinate_system})
gis_ds_view.define_shared_variable(
:fcsi_sr2cs_name,
## This is a hash_table keyed on the Spatial Refernce code and values are
## the internal names of coordinate systems that belong to the
## EPSG code.
hash_table.new_with(
7030,{"world_longlat_wgs84_degree"},
54003,{"world_miller_wgs84_cm"}
),
:public)
$
_pragma(classify_level=basic, topic={fcsi,coordinate_system})
_method gis_ds_view.fcsi_spatial_reference_coordinate_systems(code,_optional unit)
## Parameters : code - the EPSG/ESRI code (eg, 6340, 6349, 53003) (number)
## unit - unit symbol to return
## Returns : collection of cooridnate system objects
## Function :
## matches one of the following.
## the abbrev field on sw_gis!coordinate_system
## the name starts with epsg includes epsg_code
## match names defined in the shared variable
## gis_ds_view.fcsi_sr2cs_name
## Methodology : badsed on numbers of http://spatialreference.org
#---------------- HISTORY ---------------------
# (2014/12/03 - Mark Field (FCSI)): Created.
#----------------------------------------------
_local cs_table << ds_coordinate_system.coordinate_system_collection(_self)
_local pred << predicate.eq(:abbrev, code.write_string)
_local rs << rwo_set.new()
rs.add_all(cs_table.select(pred))
pred << predicate.wild(:name,"epsg*"+code.write_string)
_local csName,nonNum
_for aCS _over cs_table.select(pred).fast_elements()
_loop
_if rs.includes?(aCS)
_then
_continue
_endif
csName << aCS.name.trim_spaces()
nonNum << _for a _over csName.size.downto(1)
_loop
_if csName[a].value < 48 _orif
csName[a].value > 57
_then
_leave _with a+1
_endif
_finally
_leave _with 1
_endloop
_if csName.subseq(nonNum).as_number() = code
_then
rs.add(aCS)
_endif
_endloop
_local map << _self.fcsi_sr2cs_name[code]
_local cs
_if map _isnt _unset
_then
_for aName _over map.fast_elements()
_loop
_if (cs << cs_table.at(aName)) _isnt _unset
_then
rs.add(cs)
_endif
_endloop
_endif
_if unit _isnt _unset
_then
_for aCS _over rs.elements()
_loop
_if aCS.unit_name _isnt unit
_then
rs.remove(aCS)
_endif
_endloop
_endif
_return rs
_endmethod
$
Record/Table Joins
General Information
These are methods that can be run on the join field (coll.all_fields[;join_fld]) to provide information
- result_flavour returns :record, :records, :fields, or :text. This helps to idenify if it is a single relationship or multiple.
Field Type Conversion
If you need to convert a string to a field type you can try using a_fld.type.class.from_write_string("123.6"). handles strings, intergers and floats.