Kingdom of Saudi Arabia · National Land Evaluation · Database Application

Database Schema

Logical design for the national evaluation database. Nine schemas, thirty-nine tables, four hundred and sixty-two columns. Target platform PostgreSQL 16 / PostGIS 3.4. No physical implementation exists.

Schemas9
Tables39
Columns462
GridHexagonal · 1 ha
Cells~215 M
Scope of this document

Logical design only. No physical implementation exists. Column types indicate intent; DDL has not been written. Cardinality estimates assume national coverage at L0, the 1 ha cell.

Target platform: PostgreSQL 16 with PostGIS 3.4 and the PostGIS extension. Storage estimates assume default page layout and no compression.

All 39 tables are documented in the Tables tab. ref 12 · geo 4 · obs 1 · thr 4 · crop 2 · src 3 · res 3 · conf 4 · wx 5 — one sub-tab per schema, 462 columns in total. The Reference and Confidence sub-tabs carry seeded values inside the card where the values are settled.

The Lookup tab holds no tables. Its 22 entries are controlled vocabularies — two to seven values each, feeding one column apiece — held as rows in ref.domain_value. src.data_source.origin, obs.cell.aquifer_type and res.area_ledger.tier are typical. As separate tables they would add 22 tables and 22 foreign keys, and adding a permitted value would need a migration; as rows they carry label_ar, sort_order and is_active, and adding one is an INSERT.

The number on each tab counts what that tab contains. Tables counts tables; Lookup counts vocabularies; Design counts 8 design decisions, Class ranges 52 elements, Lineage 9 pipeline hops.

Design decisions

D-01
Custom hexagonal grid, L0
Cell identity is a bigint cell identifier; no per-cell geometry is stored. Boundary polygons are generated on demand via grid.cell_boundary(). Hexagonal tessellation gives uniform 6-neighbour adjacency at constant edge distance, which removes the diagonal-vs-orthogonal ambiguity present in square-grid contiguity tests. Approximately 215 M cells over the national land area (2.15 M km² ÷ 10,000 m²). A standard indexing system was considered and rejected: no H3 resolution equals one hectare — resolution 10 is 1.505 ha and resolution 11 is 0.215 ha, which would take the grid to about 1 000 M cells. A custom hexagonal grid delivers exactly the one-hectare cell named in the Terms of Reference.
D-02
Denormalised observation tables, one per module
Four tables of 19, 15, 6 and 26 columns rather than a single EAV table or 66 narrow tables. Estimated heap plus index: 0.11 TB against 0.80 TB (EAV) and 0.60 TB (66 tables). The saving is the cell key stored once per row rather than 66 times. Typed columns also remove the value_num/value_text polymorphism an EAV design requires.
D-03
Observations are materialised
Measured values are persisted alongside the class they produced. Threshold revision then requires a reclassification query over obs.* rather than reprocessing source rasters. Given that no threshold version has been approved, revision is expected.
D-04
Threshold versioning
All threshold rows carry version_id. Supersession sets effective_to; rows are not deleted. Result tables carry the version used, so outputs from different versions are distinguishable and not silently comparable.
D-05
Governing element is recorded
Class assignment uses MAX(rank) over member elements. classify.element_breakdown().is_governing and classify.crop_breakdown().governing_element identify which element produced the assignment, making any class traceable to a single observation without recomputation.
D-06
Source origin discriminator
src.data_source.origin takes external or ministry. Rows with origin = 'ministry' have no acquirable substitute and constitute the project's external dependency set.
D-07
Confidence is derived from the governing element
Class confidence is the confidence of the element that determined the class, or MIN() where elements tie. Aggregating across all elements would report a value inconsistent with the assignment rule.
D-08
Partitioning strategy
obs.*, res.* and conf.* are LIST-partitioned on province_id (13 partitions). Provincial delivery is the primary access pattern, giving partition pruning on most queries. classify.element_breakdown() is sub-partitioned by element_code given its estimated 9.4 B rows.

Conventions

Naming and type conventions
Schema prefixEight schemas by function: ref thr crop geo obs res conf src. Cross-schema FKs are permitted; circular references are not.
Identifierssnake_case, lower case. Surrogate keys are <entity>_id. Natural keys use the domain code, e.g. ref.element.element_code.
Units in column namesPhysical columns carry their unit as a suffix: rooting_depth_cm, ece_ds_m, etc_m3_ha. Removes unit ambiguity at query time.
Numeric typesreal for measured continuous values (7 significant digits is sufficient given source precision). numeric(3,2) for confidence scores where exact decimal comparison is required. smallint for bounded integers and indices.
Spatial referenceStorage and exchange in EPSG:4326. Area and distance computed in EPSG:32637 / 32638 (UTM 37N / 38N) — the national extent spans both zones. Grid area functions are used in preference where available.
Timestampstimestamptz throughout. obs.*.obs_date is the reference date of the source data, not the load date; load metadata is held on src.source_set.
ArraysUsed where cardinality is small and bounded: res.hectare_result.cap_governing, geo.zone.viable_systems. Avoids junction tables for sets of fewer than ten short values.
NullabilityObservation columns are nullable — absence of a measurement is a valid and meaningful state, recorded in completeness. Reference and key columns are NOT NULL.
Reading a column definition. Two kinds of badge appear against a column. A LKP-nn badge means the column is fed by that lookup and accepts only its values; the CHECK constraint is generated from the lookup, so the two cannot drift apart. A 0–300 cm badge on an attribute column states its permitted range — the interval a reading must fall inside to be stored at all. These are validation bounds, not class thresholds. A rooting depth of 0–300 cm says a value of 4 000 is a data fault, not that 300 cm is a class boundary; the boundaries live in thr.class_range and remain registered for expert calibration. The bounds are physical and instrumental limits proposed for confirmation, and 106 columns carry one. Columns with neither badge hold keys, geometry, dates or free text.
A hectare may be served by more than one water source, and each is assessed separately. obs.cell is keyed on (cell_id, water_source_id), so a cell within reach of a well and a treated-wastewater outfall carries two rows. The cell takes the best class across its sources, and res.hectare_result.wat_source_id records which one produced it. Without that column the water class cannot be interpreted — a hectare can be W3 on groundwater and W1 on a desalination connection, and those are different answers to different questions.
One class range may be evaluated against a second element. thr.class_range carries an optional co_element_code with its own bounds, NULL on every one-dimensional range. WP-C-02 sodium adsorption ratio is the only element that uses it. FAO-29 assesses infiltration hazard from SAR and ECw jointly, because at a given SAR the infiltration rate improves as salinity rises — an SAR of 6 is a serious problem at ECw 0.3 dS/m and none at ECw 1.2 dS/m. A single-column range table cannot express a threshold that moves with a second measurement.

Input attributes and computed attributes

Two kinds of thing live in this database, and the whole design turns on keeping them apart.

Input attributeWhat was measured. rooting_depth_cm = 79.4. A fact about the hectare, loaded by the ETL. No threshold, no algorithm, no judgement. 49 of them.
Computed attributeWhat was derived. C2. Depends entirely on a threshold someone chose, in an admin area, under review. Not stored, except where the map cannot afford to compute it.

A class is not data — it is a function: class = f(value, threshold_version). Given 79.4 and version 1, the answer is C2 deterministically, every time. Storing it stores the answer to a sum whose operands are both already on the row.

Why this matters more than storage. The thresholds in thr.class_range are illustrative values carried from the Al Lith pilot, not calibrated national ones, and thr.version holds one version at status under_review. An admin area is being built where those parameters get set: an operator changes a class range, sees a sample, approves it.

With results stored per row, that change rewrites 215 million rows. With results computed, it is a version bump and the next query returns the new answer. The admin area is the point of the system, and stored results make its central operation expensive.

What is stored, and what is computed

AttributeStored?Why
49 measurementsYESFacts about the hectare. They do not depend on a threshold and do not change when the methodology changes.
4 module answersYESThe one legitimate cache. Every map tile filters on them, and MAX(rank) across 33 elements cannot be computed per tile at 215 M cells.
6 filter columnsYESGoverning element, confidence, fragile flag. Filtered across millions of cells with no measurement column to derive them from.
Alternative water sourcesJSONNever classified, never filtered nationally. Context for one cell at a time.
Per-element classNOf(measurement, thr.class_range). The panel reads one cell — 33 values against 85 threshold rows, sub-millisecond.
Per-element rankNOThe rank of the class in ref.class.
Per-element confidenceNOMethod × resolution scores are constant per source; boundary distance is one subtraction.
Per-element fragile flagNOIs the value within 1σ of a boundary. One comparison.
Crop suitabilityNOA comparison against thr.crop_requirement. Storing it was 4.3 billion rows holding an answer that goes stale.

Filtering the map without stored classes

A class filter becomes a value-range filter, resolved before the scan:

-- “show cells where salinity is C4”
SELECT value_lo, value_hi FROM thr.class_range
 WHERE element_code = 'LQ-SC-01' AND class_id = 4 AND version_id = $1;
--> 8, 16

SELECT cell_id FROM obs.cell
 WHERE ece_ds_m >= 8 AND ece_ds_m < 16;

Step 1 hits an 85-row table that stays in memory permanently. Step 2 is an indexed range scan on an ordinary column — the same index type and the same speed as filtering a stored class, and it follows a threshold change immediately instead of after a reprocessing run. Index the measurement columns people filter on: ece_ds_m, rooting_depth_cm, slope_pct, sand_encr_m_y.

Version history comes back for free. Measurements carry no version_id, because a measurement does not depend on a threshold. Ask for v1 and join thr.class_range at v1; ask for v2 and join at v2. Both answerable from the same row, so a published figure stays reproducible — which for a ministry deliverable is a requirement, not a convenience.
The principle, stated once. Store what was measured. Compute what was decided. Materialise only what the map cannot afford to compute.
Why the measurements sit in one table. Sixteen elements are the same measurement rated against two threshold sets — LQ-SP-03 and SQ-A-03 are both rooting depth, one compared against thr.class_range for capability and the other against thr.crop_requirement for a named crop. Storing them separately would put the same number in two places, and two copies of one measurement diverge the first time one ETL job re-runs and the other does not.

obs.cell therefore holds one row per hectare with 33 measurements: 17 capability, 6 land rights, and the 10 suitability factors that are genuinely their own. The 16 mirrors carry no column of their own — ref.element.storage_column points them at the capability column, and the classification routine reads one value twice.

obs.cell stays separate, and this is not an inconsistency. It is keyed on (cell_id, water_source_id), because a hectare can be served by a well and a desalination connection at once, each with its own salinity, lift and licence. Folding it into a per-cell row would force one source per hectare and silently discard the alternative — which is exactly the comparison an investment case turns on.

Reading a class code — how the text is composed

The system never parses the composite code. C4s is stored for display, but the parts are already separate columns: cap_class_id, cap_subclass and cap_governing. The interface joins three reference tables and composes a sentence.

SELECT c.code,
       COALESCE(n.override_en,
                c.plain_en || CASE WHEN r.cap_subclass IS NULL THEN ''
                                   ELSE ' The limitation is ' || s.phrase_en || '.' END
       )                                   AS headline,
       c.implication_en                    AS what_it_means,
       e.name_en, e.plain_description      AS governing_element
FROM   res.hectare_result r
JOIN   ref.class    c ON c.class_id     = r.cap_class_id
LEFT   JOIN ref.subclass s ON s.letter  = r.cap_subclass
LEFT   JOIN ref.element  e ON e.element_code = r.cap_governing
LEFT   JOIN ref.class_note n
         ON n.class_id = r.cap_class_id
        AND (n.subclass IS NULL OR n.subclass = r.cap_subclass)
        AND n.is_active
WHERE  r.cell_id = $1 AND r.version_id = $2;

Composing rather than storing every combination means adding a subclass letter costs one row, not five, the Arabic is written once per class and once per letter rather than once per pair, and C4s and C4z are guaranteed to differ in exactly one clause.

Composed in layers — a card shows two, a detail panel shows five
ref.class.plain_enThis land is severely limited.
ref.subclass.phrase_enThe limitation is a soil physical property.
ref.element + the valueRooting conditions, at 42 cm.
ref.element.plain_descriptionHow deep roots can go before rock or hardpan stops them.
ref.class.implication_enExpect reduced yield and a short list of suitable crops.

Class text — all 19

CodeWhat it meansWhat it means for a decision
C1 overrideThis is good farmland. Nothing about the land itself gets in the way.Any crop the climate and water allow can be grown here without working around the land.
C2This is workable farmland with one thing to manage.Most crops are possible. The limitation adds cost or care rather than closing options.
C3This land can be farmed, but a real limitation has to be worked around.Crop choice narrows and management effort rises. Viable, but not for every crop.
C4This land is severely limited. It can be used, but only for crops that tolerate the problem.Expect reduced yield and a short list of suitable crops. Assess the cost of the limitation before committing.
CNThis land cannot support cultivation as it stands.Not usable without reclamation, and reclamation may not be economic. Treat as unavailable for cropping.
W0 overrideThe water situation is unknown.No water record is held for this hectare. This is not a finding of availability and must not be read as one.
W1Water is available and sustainable.Supply supports the activity without depleting the source.
W2Water is available with a caution.Usable, but one parameter needs watching — quality, decline rate or delivery cost.
W3Water is a serious constraint.Supply limits what can be grown or how much land can be irrigated. Plan around it, not past it.
W4There is no usable water. Nothing can be grown here regardless of the soil.Water is the blocker, not the land. Until a supply exists, soil quality is academic.
E0 overrideNobody has checked yet. The legal state of this hectare is unknown.None of the six registers is available. This is recorded as unknown and is never treated as permission.
E1Cleared on all six legal checks.No designation constrains this hectare in the registers held.
E2Development is possible but conditional.A permit, a resolution or a change of designation is required before work begins.
E3Development is barred.No soil or water improvement changes this. Do not plan development here.
S1 overrideHighly suitable for this crop.Expect full yield potential with normal management.
S2Moderately suitable for this crop.Yield or management cost is affected, but the crop performs.
S3Marginally suitable for this crop.The crop will grow, but the margin between cost and return is thin. Check a better-matched crop first.
N1 overrideNot suitable for this crop under current conditions.A different crop, or reclamation, may change this. Not a permanent verdict.
N2 overridePermanently unsuitable for this crop.The limitation cannot be economically corrected. Choose a different crop or a different hectare.
Six combinations carry an override, and each prevents a specific misreading. E0 and W0 would compose with no limitation clause, which reads as cleared — the exact misreading locked rule 8 exists to prevent. C1 and S1 carry no subclass letter, so the clause is omitted rather than left empty. N1 and N2 both render as N, because nothing yet distinguishes currently from permanently unsuitable. ref.class_note.reason records why each exists — without it a later editor deletes the row as redundant and reintroduces the defect.

Subclass phrases — the clause that completes the sentence

Noun phrases, so they compose cleanly in both languages. The Arabic agrees with the Arabic sentence frame rather than translating the English one word for word.
LetterEnglishArabic
sa soil physical propertyخاصية فيزيائية للتربة
zsalinity or sodicityالملوحة أو الصودية
na nutrient or toxicity problemمشكلة غذائية أو سمّية
wwater or drainageالمياه أو الصرف
fflood exposureالتعرض للفيضان
tthe terrainالتضاريس
eerosionالتعرية
dadvancing sandزحف الرمال
cthe climateالمناخ
iirrigation demandالاحتياج المائي للري
qwater qualityجودة المياه
ythe sustainability of the supplyاستدامة الإمداد
vthe volume availableالحجم المتاح
aaccess to the supplyالوصول إلى الإمداد
bthe basin allocationتخصيص الحوض

Constraints — where the method is enforced by the schema

The methodological rules governing this study are not left to application code. Where a rule can be expressed as a database constraint it is expressed as one, so that a value violating it cannot be stored at all. The list below is the set of constraints that carry methodological weight; ordinary referential integrity is not itemised.

Enforced constraints
Class schemes cannot mixEvery class-bearing column is FK to ref.class, and carries a CHECK that the referenced row belongs to the scheme declared on its module. A capability column cannot hold S2; a suitability column cannot hold C2. The S1–N2 series is reachable only from suitability.
No averaging path existsNo table holds a numeric composite of class values. res.hectare_result carries three separate class columns and no combined score column. There is nowhere to write an average, which is a stronger guarantee than a rule not to compute one.
ALUES weight is inertthr.crop_requirement.weight is retained for source fidelity and is referenced by no generated column, no view and no classification routine. It is provenance, not an input.
One selected water sourcePartial unique index on obs.cell (cell_id, version_id) WHERE is_selected. A cell may carry several source rows but exactly one may be marked as the source of the published class.
Governing element is uniquePartial unique index on classify.element_breakdown() (cell_id, module_id, version_id) WHERE is_governing. Exactly one element may be recorded as governing per cell per module; ties are resolved to the lower confidence before the flag is set.
Threshold intervals cannot overlapEXCLUDE constraint on thr.class_range over (element_code WITH =, version_id WITH =, numrange(low, high) WITH &&). Two classes cannot claim the same value. Supersession is CHECK (effective_to IS NULL OR effective_to > effective_from); rows are never deleted.
Results carry their versionversion_id is NOT NULL and part of the primary key on every result and confidence table. A result produced under one threshold version cannot be silently compared with another, because the two cannot occupy the same key.
Absence is not permissionThe six obs.land_rights columns DEFAULT to E0 and are never inferred upward. An unrecorded legal state is recorded as unknown and counted against completeness; it is never promoted to E1. Unknown is not the same finding as clear.
Terminal classes are declaredref.class.is_terminal is TRUE for CN, W4, E3 and N2. Downstream development categories read the flag rather than string-matching class codes.
Zoning stays crop-agnosticgeo.zone has no crop column and no FK to crop.crop. Crop verdicts reach zones only through res.zone_crop, which is an attribute table. A crop cannot participate in forming a zone boundary because the boundary table cannot reference it.
Element catalogue must resolveref.element.storage_table and storage_column are validated against information_schema.columns at deployment. A catalogue entry pointing at a column that does not exist fails the build rather than producing silent nulls at classification time.
Confidence is boundedAll confidence columns are numeric(3,2) CHECK BETWEEN 0 AND 1. Band assignment is a generated column from the score, not an independently written value, so score and band cannot disagree.

Estimated volumes at national coverage

Cardinality and storage
geo.cell~215 M rows · ~7 GB. No geometry column.
obs.* (4 tables)~215 M rows each · ~105 GB total heap and index.
classify.element_breakdown()~9.4 B rows per threshold version · largest table in the design. Sub-partitioned by element. Candidate for BRIN indexing on cell_id given cell identifier locality.
classify.element_breakdown()~9.4 B rows per version · same partitioning strategy as classify.element_breakdown().
classify.crop_breakdown()215 M × crops × production systems. Materialising all 63 crops against all 8 systems is not intended; population is restricted to crop-system pairs under active assessment.
geo.zoneNot estimable until the national exclusion and dissolve passes have run.
What a lookup is, in this design

A controlled vocabulary: a short closed list of permitted values attached to one column. Every entry here is held as rows in ref.domain_value, with a CHECK constraint generated from it. Nothing in this tab is a table.

Reference entities that are tables — the 64 elements, the 19 classes, the 25 units, the 16 authorities, the 13 provinces — are documented in the Tables tab under Reference, where each card carries its column definitions and its seeded values together.

These 22 are rows rather than tables because each is two to seven values feeding a single column. As tables they would add 22 tables and 22 foreign keys, and adding a permitted value would need a migration. As rows they carry label_ar, sort_order and is_active — none of which a bare CHECK constraint can hold — and adding one is an INSERT.

dom
Controlled vocabularies
Twenty-two closed lists, each feeding one named column. Identical structure throughout: id, code, English name, Arabic name, description.
22 vocabularies
93 values
Arabic is drafted, not authoritative. Every name_ar below is a first draft written for correction. The Arabic Execution Plan and the bilingual Data Requirements Matrix already fix terminology for this engagement, and those terms take precedence wherever they differ.
HLKP-08Sectorالقطاعref.production_system.sector5 values▾
idcodename_enname_ardescription
1cropCrop agricultureالزراعة النباتيةFour production systems
2livestockLivestockالثروة الحيوانيةOne production system
3aquacultureAquacultureالاستزراع المائيOne production system
4agroindustryAgro-industryالصناعات الزراعيةOne production system
5land_managementLand managementإدارة الأراضيOne production system
KLKP-11Crop groupمجموعة المحاصيلcrop.crop.crop_group7 values▾
idcodename_enname_ardescription
1cerealCerealالحبوب
2fruitFruitالفاكهة
3vegetableVegetableالخضروات
4pulsePulseالبقوليات
5forageForageالأعلاف
6oilseedOilseedالبذور الزيتية
7root_tuberRoot and tuberالجذور والدرنات
MLKP-13Acquisition methodطريقة الحصول على البياناتclassify.element_breakdown() — confidence component 15 values▾
idcodename_enname_ardescription
1field_measuredField measuredقياس ميدانيscore 1.00 · no element currently qualifies
2ministry_recordMinistry recordسجل وزاريscore 0.95
3satellite_directSatellite directقياس فضائي مباشرscore 0.85
4satellite_modelledSatellite modelledنمذجة من بيانات فضائيةscore 0.70
5inferredInferredمستنتجscore 0.55
NLKP-14Threshold maturityنضج العتباتthr.crop_requirement.validation_status — confidence component 44 values▾
idcodename_enname_ardescription
1operationalOperationalتشغيليscore 1.00 · calibrated for Saudi conditions
2expert_reviewedExpert reviewedمراجَع من خبراءscore 0.92
3source_validatedSource validatedموثّق من المصدرscore 0.80 · every current row
4extractedExtractedمستخرجscore 0.65
No threshold version exceeds source_validated, which caps confidence component 4 at 0.80 across every output.
OLKP-15Source originمنشأ المصدرsrc.data_source.origin2 values▾
idcodename_enname_ardescription
1externalExternalخارجيObtainable without ministry involvement
2ministryMinistryوزاريCannot be derived externally at any resolution
The two-value split that defines the whole project dependency set. All six obs.land_rights columns are ministry-origin.
PLKP-16Acquisition statusحالة الحصول على البياناتsrc.data_source.acquisition_status5 values▾
idcodename_enname_ardescription
1not_startedNot startedلم يبدأ
2requestedRequestedتم الطلب
3negotiatingNegotiatingقيد التفاوض
4heldHeldمتوفر
5blockedBlockedمتعذرDrives the critical path
QLKP-17Licenceالترخيصsrc.data_source.licence4 values▾
idcodename_enname_ardescription
1cc_by_4CC-BY 4.0رخصة المشاع الإبداعي 4.0
2copernicusCopernicus openرخصة كوبرنيكوس المفتوحة
3restrictedRestrictedمقيّد
4not_yet_agreedNot yet agreedلم يُتفق عليه بعدTypical of ministry sources
RLKP-18Access routeطريقة الوصولsrc.data_source.access_route4 values▾
idcodename_enname_ardescription
1apiAPIواجهة برمجية
2bulk_downloadBulk downloadتنزيل مجمّع
3formal_requestFormal requestطلب رسمي
4mouMoU requiredيتطلب مذكرة تفاهم
SLKP-19Update cycleدورة التحديثsrc.data_source.update_cycle4 values▾
idcodename_enname_ardescription
1staticStaticثابت
2annualAnnualسنوي
3revisit_5d5-day revisitإعادة زيارة كل 5 أيامSentinel-2
4on_requestOn requestعند الطلب
TLKP-20Coverageالتغطيةsrc.data_source.coverage4 values▾
idcodename_enname_ardescription
1globalGlobalعالمي
2regionalRegionalإقليمي
3nationalNationalوطني
4partialPartialجزئي
ULKP-21Derivation typeنوع الاشتقاقsrc.element_source.derivation5 values▾
idcodename_enname_ardescription
1directDirectمباشرSensor reading used as measured
2indexIndexدليلComputed band index
3modelModelنموذجModel prediction — SoilGrids
4proxyProxyمؤشر بديلStands in for the quantity
5lookupLookupجدول مرجعيRead from a register
VLKP-22Water source typeنوع مصدر المياهobs.cell.source_type — WP-A-016 values▾
idcodename_enname_ardescription
1WRRenewable groundwaterمياه جوفية متجددة
2WFFossil groundwaterمياه جوفية غير متجددة
3WMManaged aquifer rechargeتغذية جوفية مُدارة
4WTTreated wastewaterمياه صرف معالجةOnly source for which WP-C-05 is non-null
5WDDesalinated waterمياه محلاة
6WSSurface waterمياه سطحية
WLKP-23Aquifer typeنوع الطبقة الحاملة للمياهobs.cell.aquifer_type — WP-B-023 values▾
idcodename_enname_ardescription
1renewableRenewableمتجددة
2fossilFossilغير متجددة
3managedManagedمُدارة
XLKP-24Tenure detailتفصيل الحيازةobs.land_rights.et_detail4 values▾
idcodename_enname_ardescription
1unrecordedUnrecordedغير مسجلةUnknown — not the same as clear
2disputedDisputedمتنازع عليها
3injunctionInjunctionقرار قضائي
4holder_confirmedHolder confirmedمالك مؤكد
YLKP-25Exclusion classسبب الاستبعادgeo.cell.exclusion_class4 values▾
idcodename_enname_ardescription
1not_landNot landليست يابسةPermanent
2physically_impossiblePhysically impossibleمتعذر فيزيائيًاPermanent
3legally_barredLegally barredمحظور قانونًاPermanent unless designation changes
4allocated_otherAllocated to other useمخصصة لاستخدام آخرThe only reversible exclusion
ZLKP-26Area categoryفئة المساحةres.area_ledger.category5 values▾
idcodename_enname_ardescription
1readyReadyجاهزةThe headline figure
2blocked_paperworkBlocked — paperworkمعطلة — إجراءاتLegal state resolvable
3blocked_waterBlocked — waterمعطلة — المياهWater state binding
4marginalMarginalهامشية
5not_developableNot developableغير قابلة للتطويرTerminal in at least one module
AALKP-27Reporting tierمستوى التقريرres.area_ledger.tier3 values▾
idcodename_enname_ardescription
1nationNationالوطنOne row
2provinceProvinceالمنطقة13 rows
3governorateGovernorateالمحافظة~130 rows · blocked until MOMAH boundaries are held
ABLKP-28Directionاتجاه التقييمref.element.direction4 values▾
idcodename_enname_ardescription
1higher_betterHigher is betterالأعلى أفضلLQ-SP-03 rooting depth
2lower_betterLower is betterالأقل أفضلLQ-SC-01 salinity
3optimum_rangeOptimum rangeنطاق أمثلSQ-B-07 soil pH
4categoricalCategoricalفئويNo ordering — WP-A-01 source type
Without a recorded direction an element cannot be rated. This is why the eleven index-valued elements need their range and direction registered before calibration.
ACLKP-29Data typeنوع البياناتref.element.data_type4 values▾
idcodename_enname_ardescription
1numericNumericرقمي عشري
2integerIntegerرقم صحيح
3textTextنصي
4booleanBooleanمنطقي
Must agree with the column resolved through ref.element.storage_column — validated at deployment.
ADLKP-30Version statusحالة الإصدارthr.version.status4 values▾
idcodename_enname_ardescription
1draftDraftمسودة
2under_reviewUnder reviewقيد المراجعةv1.0-alues
3approvedApprovedمعتمد
4supersededSupersededمُستبدلeffective_to set — row never deleted
AELKP-31Applicability markرمز الانطباقthr.element_applicability.mark4 values▾
idcodename_enname_ardescription
1GGovernsحاكمParticipates in MAX(rank)
2NDoes not applyلا ينطبقExcluded for this system
3QQualifies (inverted)مؤهِّل (معكوس)Hazard selects rather than excludes
4CConditionalمشروطApplies only under stated condition
64 elements × 8 production systems = 512 rows.
AFLKP-32Source systemنظام المصدرthr.crop_requirement.source_system3 values▾
idcodename_enname_ardescription
1ALUES_0.2.1ALUES 0.2.1ألوس 0.2.11,268 threshold records · 56 crops
2FAO_ECOCROPFAO ECOCROPإيكوكروب — الفاو7 Saudi-priority crops with full profiles
3SAUDI_CALIBRATIONSaudi calibrationمعايرة سعوديةReserved — no rows yet
ref
Reference
Static reference data. Nothing here varies by cell, by crop or by threshold version — that is the membership test for this schema. ref.element is the join point of the whole database, carrying storage_table and storage_column so the classification routine resolves columns from the catalogue rather than from hard-coded mapping. Each card expands to its column definitions and, where the values are settled, the seeded rows themselves.
13 tables
105 columns
ref.moduleThe four assessment modules. Fixed at four; defines which question each element answers.8 col4▾
ColumnTypeKeySample dataDefinition
module_idsmallintPKNOT NULL11–4. Stable identifier used throughout.
codetextUQNOT NULL'capability'capability · water · land_rights · suitability
name_entextNOT NULL'Land Capability'Display name in English.
name_artext'القدرة الأرضية'Display name in Arabic, for bilingual output.
questiontextNOT NULL'Can this hectare physically support cultivation?'The plain-language question the module answers.
class_scheme_idsmallintFKNOT NULL1→ ref.class_scheme. Which class series this module reports in.
element_countsmallintNOT NULL1919 · 15 · 6 · 26. Denormalised for display; maintained by trigger.
sort_ordersmallintNOT NULL3Presentation sequence.
Seeded values
idcodename_enname_ardescription
1capabilityLand Capabilityالقدرة الأرضيةCan this hectare physically support cultivation? 19 elements.
2waterWater Assessmentتقييم المياهIs water lawfully and sustainably available? 15 elements.
3land_rightsLand Rights & Constraintsالحقوق والقيود على الأرضIs the hectare legally available? 6 checks.
4suitabilityCrop Suitabilityملاءمة المحاصيلWhich crops match this hectare? 26 factors.
ref.element_groupThe 19 analytical groups across the four modules. Class assignment: MAX(rank) over member elements.7 col19▾
ColumnTypeKeySample dataDefinition
group_idsmallintPKNOT NULL1
module_idsmallintFKNOT NULL1→ ref.module
letterchar(1)NOT NULL's'A–F within the module. Not globally unique.
name_entextNOT NULL'Soil physical'e.g. Soil Physical · Sustainability · Water Quality
name_artext'خصائص التربة الفيزيائية'
subclass_letterstext'{s}'Letters this group can emit, e.g. 'z,n' for Soil Chemical.
sort_ordersmallintNOT NULL3
ref.elementThe catalogue of all 64 assessed elements. Referenced by thr.*, src.element_source, obs.*, res.* and conf.*.15 col66▾
ColumnTypeKeySample dataDefinition
element_codetextPKNOT NULL'LQ-SP-03'LQ-SP-03 · WP-B-01 · SQ-B-04 · EP. Natural key. Stable across versions; cited in published output.
module_idsmallintFKNOT NULL1→ ref.module
group_idsmallintFKNOT NULL1→ ref.element_group
name_entextNOT NULL'Rooting conditions'Rooting conditions · Water-level trend · Toxicity (boron)
name_artext'ظروف التجذير'
plain_descriptiontextNOT NULL'How deep roots can go before something stops them'Non-technical definition for UI display.
why_it_matterstextNOT NULL'Shallow soil limits every crop regardless of fertility'Agronomic or legal significance, for UI display.
unit_idsmallintFK3→ ref.unit. Null for categorical elements such as the six legal checks.
subclass_letterchar(1)FK's'→ ref.subclass. Null where the element cannot emit a subclass.
directiontext'higher_better'higher_better · lower_better · optimum_range · categorical. Governs interpolation.
storage_tabletextNOT NULL'obs.capability'obs.capability · obs.cell · obs.land_rights · obs.suitability
storage_columntextNOT NULL'rooting_depth_cm'The physical column holding this element's value. Allows the classification routine to resolve columns dynamically rather than by hard-coded mapping.
data_typetextNOT NULL'numeric'numeric · integer · text · boolean — the column's storage type.
is_activebooleanNOT NULLTRUEFALSE excludes the element from processing without deleting dependent history.
sort_ordersmallintNOT NULL3
Seeded values
idcodename_enname_ardescription
1LQ-SP-01Available water capacityالسعة المائية المتاحةawc_mm_m · mm/m · s
2LQ-SP-02Soil workabilityقابلية التربة للحراثةworkability_idx · index · s
3LQ-SP-03Rooting conditionsظروف التجذيرrooting_depth_cm · cm · s
4LQ-SP-04Surface sealing and crustingانسداد وتقشر سطح التربةsealing_idx · index · s
5LQ-SC-01Salinity (ECe)الملوحةece_ds_m · dS/m · z
6LQ-SC-02Sodicity (ESP)الصوديةesp_pct · % · z
7LQ-SC-03Nutrient availabilityتوافر العناصر الغذائيةnutrient_idx · index · n
8LQ-SC-04Toxicity (boron)السمية (البورون)boron_mg_l · mg/L · n
9LQ-W-01Drainage conditionحالة الصرفdrainage_class · index · w
10LQ-W-02Flood hazardخطر الفيضانflood_ev_10y · events/10 yr · f
11LQ-W-04Waterlogging riskخطر التشبع بالمياهwaterlog_d_y · days/yr · w
12LQ-T-01Terrain (slope)التضاريس (الانحدار)slope_pct · % · t
13LQ-T-02Water erosionالتعرية المائيةerosion_w_t_ha · t/ha/yr · e
14LQ-T-03Wind erosionالتعرية الريحيةerosion_wind_t_ha · index · e
15LQ-T-04Sand encroachmentزحف الرمالsand_encr_m_y · m/yr · d
17LQ-C-02Thermal regimeالنظام الحراريgdd · °C·day · c
18LQ-C-03Radiationالإشعاع الشمسيradiation_mj · MJ/m²/day · c
20WP-A-01Source typeنوع المصدرsource_type · category
21WP-A-02Available volumeالحجم المتاحavail_vol_m3_ha · m³/ha/yr · v
22WP-A-03Distance to sourceالمسافة إلى المصدرdist_source_km · km · a
23WP-B-01Water-level trendاتجاه منسوب المياهlevel_trend_m_y · m/yr · y
24WP-B-02Aquifer typeنوع الطبقة الحاملةaquifer_type · category · y
25WP-B-03Remaining supply horizonأفق الإمداد المتبقيsupply_horizon_y · years · y
26WP-C-01Irrigation water salinityملوحة مياه الريecw_ds_m · dS/m · q
27WP-C-02Sodium adsorption ratioنسبة امتزاز الصوديومsar · ratio · q
28WP-C-03Chlorideالكلوريدchloride_mg_l · mg/L · q
29WP-C-04Boron in irrigation waterالبورون في مياه الريboron_w_mg_l · mg/L · q
30WP-C-05Treated wastewater tierدرجة مياه الصرف المعالجةww_tier · category · q
31WP-D-01Pumping liftارتفاع الضخpump_lift_m · m · a
32WP-D-02Conveyance distanceمسافة النقلconveyance_km · km · a
33WP-E-01Basin sustainable yieldالعائد المستدام للحوضbasin_yield_mm3 · Mm³/yr · b
34WP-E-02Allocation statusحالة التخصيصalloc_pct · % · b
35EPProtected areaالمناطق المحميةep_class · category · NCW · ministry
36EVRangeland, forest and afforestationالمراعي والغابات والتشجيرev_class · category · NCVC · ministry
37ETTenureالحيازةet_class · category · MOJ Watheeq · ministry
38EZZoning designationالتصنيف التخطيطيez_class · category · MOMAH · ministry
39EXConflicting useالاستخدامات المتعارضةex_class · category · MOE/MOD/MODON · ministry
40EHHazard designationتصنيف المخاطرeh_class · category · NCEC · ministry
41SQ-A-01Available water capacityالسعة المائية المتاحة← LQ-SP-01 · mm/m · s
42SQ-A-02Soil workabilityقابلية التربة للحراثة← LQ-SP-02 · index · s
43SQ-A-03Rooting conditionsظروف التجذير← LQ-SP-03 · cm · s · crop table
44SQ-A-04Surface sealing and crustingانسداد وتقشر السطح← LQ-SP-04 · index · s
45SQ-A-05Soil textureقوام التربة← LQ-SP-03 · category · s · crop table
46SQ-A-06Coarse fragmentsالشظايا الخشنة← LQ-SP-03 · % · s · crop table
47SQ-B-01Salinity (ECe)الملوحة← LQ-SC-01 · dS/m · z · crop table
48SQ-B-02Sodicity (ESP / SAR)الصودية← LQ-SC-02 · % · z
49SQ-B-04Toxicity risk (boron)خطر السمية (البورون)← LQ-SC-04 · mg/L · n · crop table
50SQ-B-05Calcium carbonateكربونات الكالسيوم← LQ-SC-03 · % · n · crop table
51SQ-B-06Gypsum contentمحتوى الجبس← LQ-SC-03 · % · n · crop table
52SQ-B-07Soil pHحموضة التربة← LQ-SC-03 · pH · n · crop table
53SQ-C-01Drainage conditionحالة الصرف← LQ-W-01 · index · w
54SQ-C-02Flood hazardخطر الفيضان← LQ-W-02 · events/10 yr · f
55SQ-C-03Waterlogging riskخطر التشبع بالمياه← LQ-W-04 · days/yr · w
56SQ-D-01Terrain workabilityقابلية التضاريس للاستغلال← LQ-T-01 · % · t · crop table
57SQ-D-02Water erosion hazardخطر التعرية المائية← LQ-T-02 · t/ha/yr · e
58SQ-D-03Wind erosion hazardخطر التعرية الريحية← LQ-T-03 · index · e
59SQ-D-04Sand encroachment hazardخطر زحف الرمال← LQ-T-04 · m/yr · d
60SQ-E-01Moisture deficit (aridity)العجز الرطوبي← SQ-E-01 · index · c
61SQ-E-02Thermal suitabilityالملاءمة الحرارية← LQ-C-02 · °C·day · c · crop table
62SQ-E-03Radiation and solar energyالإشعاع والطاقة الشمسية← LQ-C-03 · MJ/m²/day · c
63SQ-E-04Length of growing periodطول موسم النمو← SQ-E-04 · days · c
64SQ-E-05Frost riskخطر الصقيعdays/yr · c · crop table · split from SQ-E-02
65SQ-F-01Irrigation demand (ETc)الاحتياج المائي للريmm/season · i · crop table
66SQ-F-02Crop nutrient requirementالاحتياج الغذائي للمحصولkg/ha · n
The catalogue and the join point of the whole database. Nutrient availability sits on the capability side as LQ-SC-03 only — it is a land property rather than a crop diagnostic, so the suitability module carries no equivalent factor. z is reserved for salinity and sodicity; carbonate, gypsum and pH are nutrient and toxicity limitations and carry n. Description column reads: storage_column · unit · subclass letter.
ref.class_schemeThe four class series. Enforces that class codes cannot be compared or mixed across modules.5 col4▾
ColumnTypeKeySample dataDefinition
class_scheme_idsmallintPKNOT NULL1
codetextUQNOT NULL'C'C · W · E · S
name_entextNOT NULL'Capability class series'Capability class · Water state · Legal state · Suitability class
member_countsmallintNOT NULL55 · 5 · 4 · 5
notetext'Project-adapted, not a formal FAO standard'Standing rule: series are never mixed in one token.
Seeded values
idcodename_enname_ardescription
1CCapability class seriesسلسلة فئات القدرةC1–CN. Project-adapted, not a formal FAO standard.
2WWater state seriesسلسلة حالات المياهW0–W4. Project-defined.
3ELegal state seriesسلسلة الحالات القانونيةE0–E3. Project-defined.
4SSuitability class seriesسلسلة فئات الملاءمةS1–N2. FAO notation, reserved to suitability.
ref.classEvery class value across the four schemes, with its severity rank.14 col19▾
ColumnTypeKeySample dataDefinition
class_idsmallintPKNOT NULL4
class_scheme_idsmallintFKNOT NULL1→ ref.class_scheme
codetextNOT NULL'C4'C1 C2 C3 C4 CN · W0 W1 W2 W3 W4 · E0 E1 E2 E3 · S1 S2 S3 N1 N2
ranksmallintNOT NULL4Severity order. Class assignment uses MAX(rank); this column defines the ordering.
label_entextNOT NULL'Capability class 4'Highly suitable · Moderately capable · Prohibited
label_artext'فئة القدرة 4'
rating_losmallint61Lower bound of the parametric rating range, 0–100. Used only for method comparison.
rating_hismallint80Upper bound. Null for non-numeric schemes.
hex_colourchar(7)NOT NULL'02'Display colour. Centralised to enforce consistent rendering.
is_terminalbooleanNOT NULLFALSETRUE for CN, W4, E3, N2. Terminal classes exclude the record from downstream development categories.
plain_entextNOT NULL'This land is severely limited…'What the class means, in plain language. The sentence a user reads, not a category name. Composed with the subclass phrase at run time.
plain_artext'أرض شديدة التقييد…'The same in Arabic.
implication_entext'Expect reduced yield and a short list…'What it means for a decision. Shown in the detail panel, omitted on a card.
implication_artext'توقّع غلة أقل…'The same in Arabic.
Seeded values
idcodename_enname_ardescription
1C1Capability class 1فئة القدرة 1rank 1
2C2Capability class 2فئة القدرة 2rank 2
3C3Capability class 3فئة القدرة 3rank 3
4C4Capability class 4فئة القدرة 4rank 4
5CNCapability class Nفئة القدرة Nrank 5 · terminal
6W0Water state 0حالة المياه 0rank 0
7W1Water state 1حالة المياه 1rank 1
8W2Water state 2حالة المياه 2rank 2
9W3Water state 3حالة المياه 3rank 3
10W4Water state 4حالة المياه 4rank 4 · terminal
11E0Legal state 0الحالة القانونية 0rank 0 · Unknown legal state — never promoted
12E1Legal state 1الحالة القانونية 1rank 1 · Legal state 1
13E2Legal state 2الحالة القانونية 2rank 2 · Legal state 2
14E3Legal state 3الحالة القانونية 3rank 3 · Legal state 3 · terminal
15S1Suitability class S1فئة الملاءمة S1rank 1
16S2Suitability class S2فئة الملاءمة S2rank 2
17S3Suitability class S3فئة الملاءمة S3rank 3
18N1Suitability class N1فئة الملاءمة N1rank 4 · Not currently distinguishable from N2
19N2Suitability class N2فئة الملاءمة N2rank 5 · terminal
label_en and label_ar are the published wording, fixed in the App 1 modules and transferred verbatim. The names above are structural identifiers only.
ref.subclassThe subclass letters. A letter identifies a limitation group, not an individual element.7 col15▾
ColumnTypeKeySample dataDefinition
letterchar(1)PKNOT NULL's's z n w f t e d c i q y v a b
module_idsmallintFKNOT NULL1→ ref.module. Letters are not globally unique; scope is the module.
meaning_entextNOT NULL'Soil physical'soil physical · salinity/sodicity · nutrient/toxicity · irrigation demand
meaning_artext'قيود التربة الفيزيائية'
notetext'Salinity and sodicity only'Documents cases where the letter maps to multiple elements, e.g. 's' → six Group A factors.
phrase_entextNOT NULL'a soil physical property'The clause that completes the sentence. "The limitation is a soil physical property." Written as a noun phrase so it composes cleanly.
phrase_artext'خاصية فيزيائية للتربة'The same in Arabic, agreeing with the Arabic sentence frame.
Seeded values
idcodename_enname_ardescription
1sSoil physicalقيود التربة الفيزيائيةDepth, texture, structure, coarse fragments
2zSalinity / sodicityالملوحة والصوديةThis letter only — no nutrient or pH limitation
3nNutrient / toxicityالعناصر الغذائية والسميةNutrients, toxicity, carbonate, gypsum, pH
4wWater / drainageالمياه والصرفDrainage class, water table
5fFloodالفيضانFlood hazard
6tTerrainالتضاريسSlope, relief
7eErosionالتعريةWater and wind erosion
8dSand driftزحف الرمالDune encroachment and mobility
9cClimateالمناخThermal, moisture, radiation, frost
10iIrrigation demandالاحتياج المائي للريCrop water requirement against supply
11qWater qualityجودة المياهECw, SAR, chloride, boron, treatment tier
12ySustainabilityالاستدامةLevel trend, aquifer type, recharge
13vVolumeالحجمLicensed and available volume
14aAccessالوصولDistance, lift and delivery infrastructure
15bBasinالحوضBasin allocation and abstraction licence
ref.unitUnits of measure, kept separate so display and conversion are consistent.5 col~20▾
ColumnTypeKeySample dataDefinition
unit_idsmallintPKNOT NULL3
symboltextUQNOT NULL'cm'cm · dS/m · mg/L · m³/ha/yr · MJ/m²/day
name_entextNOT NULL'Centimetre'Centimetre · Decisiemens per metre
dimensiontextNOT NULL'length'length · conductivity · concentration · volume · energy
decimal_placessmallintNOT NULL1Display precision.
Seeded values
idcodename_enname_ardescription
1m2Square metreمتر مربعArea. geo.cell mean area 10,000 m²
2haHectareهكتارArea. Reporting unit of res.area_ledger
3cmCentimetreسنتيمترLength. LQ-SP-03 · SQ-A-03
4mMetreمترLength. WP-D-01 pumping lift
5kmKilometreكيلومترLength. WP-A-03 · WP-D-02
6mm_mMillimetres per metreمليمتر/مترDepth ratio. LQ-SP-01 · SQ-A-01
7mm_seasonMillimetres per seasonمليمتر/موسمDepth. SQ-F-01 ETc
8ds_mDecisiemens per metreديسيسيمنز/مترElectrical conductivity. LQ-SC-01 · WP-C-01 · SQ-B-01
9mg_lMilligrams per litreمليغرام/لترConcentration. LQ-SC-04 · WP-C-03 · WP-C-04 · SQ-B-04
10pctPercentنسبة مئويةProportion. 7 elements
11phpH unitsدرجة الحموضةDimensionless. SQ-B-07
12ratioDimensionless ratioنسبةWP-C-02 sodium adsorption ratio
13indexDimensionless indexدليل11 elements. Range and direction not yet registered
14t_ha_yrTonnes per hectare per yearطن/هكتار/سنةMass flux. LQ-T-02 · SQ-D-02
15kg_haKilograms per hectareكيلوغرام/هكتارMass per area. SQ-F-02
16m_yrMetres per yearمتر/سنةRate. LQ-T-04 · WP-B-01 · SQ-D-04
17m3_ha_yrCubic metres per hectare per yearمتر مكعب/هكتار/سنةVolume flux. WP-A-02
18mm3_yrMillion cubic metres per yearمليون متر مكعب/سنةVolume flux. WP-E-01
19daysDaysيومDuration. SQ-E-04
20days_yrDays per yearيوم/سنةFrequency. LQ-W-04 · SQ-C-03 · SQ-E-05
21yearsYearsسنةDuration. WP-B-03
22ev_10yrEvents per ten yearsحدث/10 سنواتFrequency. LQ-W-02 · SQ-C-02
23degc_dayGrowing degree daysدرجة مئوية·يومThermal accumulation. LQ-C-02 · SQ-E-02
24mj_m2_dayMegajoules per square metre per dayميغاجول/م²/يومRadiant flux. LQ-C-03 · SQ-E-03
25categoryNon-numeric classفئة وصفيةCategorical. 10 elements
Registering the unit once is what keeps dS/m from appearing beside dS m-1 on two elements measuring the same thing.
ref.authorityThe bodies holding the records screened by the legal module, and the custodians of ministry-supplied data.7 col~12▾
ColumnTypeKeySample dataDefinition
authority_idsmallintPKNOT NULL2
codetextUQNOT NULL'NCW'NCW · NCVC · MOMRAH · MOJ · GAMEP · MOE · MOD · MODON
name_entextNOT NULL'National Center for Wildlife'National Center for Wildlife
name_artext'المركز الوطني لتنمية الحياة الفطرية'
domaintextNOT NULL'environment'environment · tenure · planning · energy · defence · hazard
urltext'https://www.ncw.gov.sa'Public register or portal.
holds_registerbooleanNOT NULLTRUETRUE where the authority is the system of record for a land_rights check.
Seeded values
idcodename_enname_ardescription
1MEWAMinistry of Environment, Water and Agricultureوزارة البيئة والمياه والزراعةClient
2NCWNational Center for Wildlifeالمركز الوطني لتنمية الحياة الفطريةSystem of record for EP protected areas
3NCVCNational Center for Vegetation Coverالمركز الوطني لتنمية الغطاء النباتيSystem of record for EV rangeland and forest
4MOJMinistry of Justice — Watheeq cadastreوزارة العدل — وثيقSystem of record for ET tenure
5MOMAHMinistry of Municipalities and Housingوزارة الشؤون البلدية والإسكانEZ zoning · governorate boundaries
6MOEMinistry of Energyوزارة الطاقةEX petroleum and mining designations
7MODMinistry of Defenceوزارة الدفاعEX military designations
8MODONSaudi Authority for Industrial Cities and Technology Zonesالمدن الصناعية ومناطق التقنيةEX industrial designations
9NCECNational Center for Environmental Complianceالمركز الوطني للرقابة على الالتزام البيئيEH hazard designation
10SWASaudi Water Authorityالهيئة السعودية للمياهWell register · monitoring network
11SGSSaudi Geological Surveyهيئة المساحة الجيولوجية السعوديةHydrogeology · lithology
12NCMNational Center for Meteorologyالمركز الوطني للأرصادClimate records
13GEOSAGeneral Authority for Survey and Geospatial Informationالهيئة العامة للمساحة والمعلومات الجيومكانيةSurvey control · base mapping
14
15NFDPNational Fisheries Development Programالبرنامج الوطني لتنمية الثروة السمكيةAquaculture
16GASTATGeneral Authority for Statisticsالهيئة العامة للإحصاءAgricultural statistics
Six separate authorities hold the six land-rights checks. They are separate registers — a hectare clear in one can be barred in another.
ref.production_systemThe eight production systems. Determines which elements apply and the minimum viable zone area.8 col8▾
ColumnTypeKeySample dataDefinition
system_idsmallintPKNOT NULL1
codetextUQNOT NULL'irrigated_open'irrigated_open · orchard · protected · rainfed · livestock · aquaculture · agroindustry · land_mgmt
name_entextNOT NULL'Irrigated open field'
name_artext'الحقل المكشوف المروي'
sectortextNOT NULL'crop'crop · livestock · aquaculture · agroindustry · land_management
min_viable_haintegerNULL50 · 10 · 2 · 20 · 1000. NULL where not yet confirmed against the Terms of Reference.
min_area_basistext'pending ToR confirmation'Documented basis for the threshold value.
is_invertedbooleanNOT NULLFALSETRUE where hazard elements select rather than exclude the record (land management only).
Seeded values
idcodename_enname_ardescription
1irrigated_openIrrigated open fieldالحقل المكشوف المرويmin_viable_ha NULL — pending ToR
2orchardOrchard / permanent cropالبساتين والمحاصيل الدائمةmin_viable_ha NULL — pending ToR
3protectedProtected cultivationالزراعة المحميةmin_viable_ha NULL — pending ToR
4rainfedRainfed croppingالزراعة المطريةmin_viable_ha NULL — pending ToR
5livestockLivestockالثروة الحيوانيةmin_viable_ha NULL — pending ToR
6aquacultureAquacultureالاستزراع المائيmin_viable_ha NULL — pending ToR
7agroindustryAgro-industryالصناعات الزراعيةmin_viable_ha NULL — pending ToR
8land_mgmtLand managementإدارة الأراضيmin_viable_ha NULL — pending ToR
ref.domainThe vocabulary registry. One row per controlled list in the design. Makes a closed set of values data rather than DDL.7 col22▾
ColumnTypeKeySample dataDefinition
domain_idsmallintPKNOT NULL6
codetextUQNOT NULL'acquisition_status'acquisition_status · origin · derivation · exclusion_class. Natural key.
applies_totextNOT NULL'src.data_source.origin'Fully qualified target, e.g. src.data_source.acquisition_status. Repeated where one vocabulary serves more than one column — which is how a collision becomes visible instead of latent.
name_entextNOT NULL'Acquisition status'Display name of the vocabulary.
descriptiontext'Where a dataset stands in the acquisition process'What the list enumerates and the rule for choosing between values.
is_closedbooleanNOT NULLTRUETRUE where the set is exhaustive and a new value requires methodological approval.
owner_roletext'method_lead'Who may add a value: method_lead · data_lead · committee.
ref.domain_valueThe permitted values themselves, with bilingual labels and display order. Referenced by CHECK constraints and by conf.component.9 col~100▾
ColumnTypeKeySample dataDefinition
domain_idsmallintPKFKNOT NULL6→ ref.domain. Composite PK with value_code.
value_codetextPKNOT NULL'satellite_modelled'The stored value, e.g. satellite_modelled.
label_entextNOT NULL'Satellite modelled'Display label in English.
label_artext'نمذجة من بيانات فضائية'Display label in Arabic. The reason this table exists — a CHECK constraint cannot carry a second language.
sort_ordersmallintNOT NULL3Presentation sequence, usually severity or lifecycle order.
is_activebooleanNOT NULLTRUEFALSE retires a value without deleting it.
first_version_idsmallintFK1→ thr.version. The threshold version at which the value entered.
notetext'Model prediction using satellite inputs'Qualification, or why a value is reserved but unused.
is_scoredbooleanNOT NULLFALSETRUE where the value carries a confidence multiplier, held in conf.component.
ref.class_noteBespoke wording for the few class and subclass combinations where composition would mislead. Returns NULL for everything else, and the interface composes normally.7 col6▾
ColumnTypeKeySample dataDefinition
class_idsmallintPKFKNOT NULL11→ ref.class.
subclasschar(1)PKNULL→ ref.subclass. NULL matches any subclass, so one row can override a whole class.
override_entextNOT NULL'Nobody has checked…'Replaces the composed sentence entirely. The interface uses this instead, never as well.
override_artext'لم يتحقق أحد…'The same in Arabic.
reasontextNOT NULL'Composition would render E0 as cleared'Why the override exists. Without it a later editor deletes the row as redundant and reintroduces the defect it was written to prevent.
is_activebooleanNOT NULLTRUEFALSE retires an override without deleting the reason.
first_version_idsmallintFK1→ thr.version. When the override entered.
ref.confidence_bandThe four published confidence bands as bounds rather than prose. Non-overlapping by constraint.6 col4▾
ColumnTypeKeySample dataDefinition
band_idsmallintPKNOT NULL2
codetextUQNOT NULL'medium'high · medium · low · very_low
lower_boundnumeric(3,2)NOT NULL0.80Inclusive. 0.80 · 0.65 · 0.50 · 0.00
upper_boundnumeric(3,2)NOT NULL1.00Exclusive except the top band. EXCLUDE constraint on the range prevents overlap.
label_entextNOT NULL'Medium confidence'Wording used in published output.
sort_ordersmallintNOT NULL3
Seeded values
idcodename_enname_ardescription
1highHigh confidenceثقة عاليةlower_bound 0.80
2mediumMedium confidenceثقة متوسطةlower_bound 0.65
3lowLow confidenceثقة منخفضةlower_bound 0.50
4very_lowVery low confidenceثقة منخفضة جدًاlower_bound 0.00
geo
Spatial
Administrative hierarchy, cell index and dissolved zone geometry.
4 tables
45 columns
geo.provinceThe 13 administrative regions. Reporting and delivery tier.7 col13▾
ColumnTypeKeySample dataDefinition
province_idsmallintPKNOT NULL'02'LKP-33
codetextUQNOT NULL'02'MKH · RYD · JOF · ASR. Used as the first segment of every zone ID.
name_entextNOT NULL'Makkah'
name_artextNOT NULL'مكة المكرمة'Required — provinces appear in Arabic on all MEWA-facing output.
geomgeometry(MultiPolygon,4326)NOT NULL'MultiPolygon(...)'MINISTRY-SUPPLIED. No external source exists.
area_hanumericNOT NULL1504.75> 0ST_Area on the projected geometry. Materialised.
assessment_area_hanumeric12840000≤ area_haArea surviving national exclusion. NULL until the national exclusion pass has run.
Seeded values
idcodename_enname_ardescription
101Riyadhالرياض
202Makkahمكة المكرمةReference region — delivered ahead of the others
303Madinahالمدينة المنورة
404Qassimالقصيم
505Eastern Provinceالمنطقة الشرقية
606Asirعسير
707Tabukتبوك
808Hailحائل
909Northern Bordersالحدود الشمالية
1010Jazanجازان
1111Najranنجران
1212Al Bahahالباحة
1313Al Joufالجوف
Thirteen values, and therefore thirteen partitions on obs.capability, obs.cell, obs.land_rights, obs.suitability and classify.element_breakdown().
geo.governorateSub-regional units. Permitting and allocation tier. Constrains zone geometry: geo.zone.governorate_id is single-valued.7 col~130▾
ColumnTypeKeySample dataDefinition
governorate_idintegerPKNOT NULL'0207'
province_idsmallintFKNOT NULL'02'LKP-33→ geo.province. Single-valued. Enforces strict containment.
codetextUQNOT NULL'0207'LTH · BUR. Second segment of the zone ID.
name_entextNOT NULL'Al Lith'
name_artextNOT NULL'الليث'
geomgeometry(MultiPolygon,4326)NOT NULL'MultiPolygon(...)'MINISTRY-SUPPLIED — MOMAH. Blocking dependency for zone generation.
area_hanumericNOT NULL1504.75> 0
geo.cellThe 1 ha hexagonal grid. No geometry column. The cell identifier encodes position.12 col~215 M▾
ColumnTypeKeySample dataDefinition
cell_idbigintPKNOT NULL20700041832cell identifier, L0. Mean cell area 10,000 m² (1 ha); 62.04 m edge, 107.46 m across flats. Boundary geometry derived via grid.cell_boundary() on demand; not materialised.
parent_r9bigintIDXNOT NULL'2070004183'Resolution-9 parent. Denormalised to avoid runtime grid.cell_parent() calls during aggregation.
parent_r8bigintIDXNOT NULL'207000418'Resolution-8 parent.
governorate_idintegerFKNOT NULL'0207'→ geo.governorate. Assigned by ST_Contains against geo.governorate at load.
province_idsmallintFKNOT NULL'02'LKP-33Denormalised from geo.governorate. Also the partition key on obs.* and res.*.
centroid_latdouble precisionNOT NULL21.421216.0–33.0°NFrom grid.cell_centroid(). Materialised for raster sampling and export.
centroid_londouble precisionNOT NULL40.187334.0–56.0°E
in_scopebooleanIDXNOT NULLTRUEFALSE where excluded at the national screening pass. Processing is restricted to TRUE rows.
exclusion_classtextNULLLKP-25allocated_other · not_land · physically_impossible · legally_barred
exclusion_detailtextNULLSource layer and rule that produced the exclusion.
exclusion_reversiblebooleanFALSEFALSE for permanent exclusions. TRUE where the designation is held by another authority and may lapse.
elevation_msmallint318−50–3200 mFrom DEM. Held on the cell rather than obs.* as it is not an assessed element.
geo.zoneDissolved groups of contiguous cells sharing identical capability, water and land_rights classes. Crop-independent.19 col~pending▾
ColumnTypeKeySample dataDefinition
zone_idtextPKNOT NULL4182Z-MKH-LTH-0147 — Composite natural key: prefix, province code, governorate code, sequence.
province_idsmallintFKNOT NULL'02'LKP-33
governorate_idintegerFKNOT NULL'0207'Single-valued. Zones do not cross governorate boundaries.
geomgeometry(MultiPolygon,4326)NOT NULL'MultiPolygon(...)'ST_Union of member cell boundaries. Materialised — this geometry is a deliverable.
cell_countintegerNOT NULL1000≥ 1Number of member cells.
area_hanumericNOT NULL1504.75> 0Sum of member cell areas.
cap_class_idsmallintFKNOT NULL4LKP-03→ ref.class. Invariant across member cells by construction.
cap_subclasstext's'LKP-04Letters of the governing group, e.g. 'nz'.
wat_class_idsmallintFKNOT NULL2LKP-03
wat_subclasstext'y'LKP-04
leg_class_idsmallintFKNOT NULL0LKP-03
leg_causetext'E0 unknown — tenure register not held'Check codes producing E2 or E3. Empty array for E1.
composite_codetextNOT NULL'C4s'C2nz · W2qy · E2(ET). Materialised for display and export.
blocking_issuetext'water'Primary constraint on development, for display.
blocking_reversiblebooleanTRUETRUE where the constraint is administrative and resolvable.
viable_systemssmallint[]'{irrigated_open,orchard}'LKP-07Production systems where area_ha ≥ ref.production_system.min_viable_ha.
below_min_forsmallint[]'{protected}'LKP-07Production systems where area_ha < min_viable_ha. Row is retained, not deleted.
threshold_version_idsmallintFKNOT NULL1Threshold version used. Zones generated under different versions are not directly comparable.
generated_attimestamptzNOT NULL'2026-03-02 09:14:22+03'
obs
Observations
One table. obs.cell holds one row per hectare: 49 measurements including the selected water source, the four module answers, and six columns materialised for map filtering. Alternative water sources sit in a jsonb column. LIST-partitioned on province_id, then HASH on cell_id.
1 tables
70 columns
What the 70 columns are
50 — inputMeasured values. 33 belonging to the cell, 16 for the selected water source, plus one jsonb holding alternative sources. Loaded by the ETL, independent of any threshold.
14 — computedMarked computed in the table below. The four module answers, the governing element and confidence per module, the fragile flag, completeness and the exclusion class. These are stored because the map filters on them across 215 M cells — MAX(rank) over 33 elements cannot be evaluated per tile.
6 — keyscell_id, province_id, version_id, obs_date, source_set_id, computed_at.
What is not on this table, and never will be. Per-element class, rank, confidence and fragile for each of the 59 scorable elements — 295 values that would be columns 71 through 365. They are a deterministic function of the 50 inputs and thr.class_range, so they are computed when a cell is opened: 33 values against 85 threshold rows, sub-millisecond.

Storing them would cost roughly 500 GB, make a threshold change a rewrite of 215 M rows rather than a version bump, and force a single threshold version per row — which would make a published figure unreproducible. Crop suitability is excluded for the same reason: it was 4.3 billion rows holding a comparison that is cheap to redo.

The 14 stored computed columns are the exception that proves the rule. Each earns its place by being filtered across millions of cells with no measurement column to derive it from. cap_governing answers “show everything limited by salinity”; no arrangement of the 50 inputs answers that without evaluating the whole comparison first.
obs.cellThe super table. One row per hectare: 49 measurements, the four module answers, and six columns materialised for map filtering. Everything else is computed on read. Capability, land rights and the ten suitability factors that are not mirrors, plus the selected water source. The 16 mirrored elements read the same column as their capability counterpart — one measurement, two thresholds, never two values.70 col~215 M▾
ColumnTypeKeySample dataDefinition
cell_idbigintPKFKNOT NULL20700041832→ geo.cell. One row per hectare.
province_idsmallintPARTNOT NULL'02'Partition key. 13 partitions.
version_idsmallintPKFKNOT NULL1→ thr.version.
obs_datedateNOT NULL'2020-01-01'Reference date of the source, not the load date.
source_set_idintegerFKNOT NULL7→ src.source_set. Which combination of sources produced this row.
awc_mm_mnumeric88.0LQ-SP-01 and SQ-A-01 read this column. Available water capacity.
workability_idxnumeric—LQ-SP-02 and SQ-A-02 read this column. Soil workability.
rooting_depth_cmnumeric79.4LQ-SP-03 and SQ-A-03 read this column. Rooting conditions.
sealing_idxnumeric—LQ-SP-04 and SQ-A-04 read this column. Surface sealing and crusting.
ece_ds_mnumeric6.95LQ-SC-01 and SQ-B-01 read this column. Salinity (ECe).
esp_pctnumeric12.0LQ-SC-02 and SQ-B-02 read this column. Sodicity (ESP).
nutrient_idxnumeric—LQ-SC-03. Nutrient availability.
boron_mg_lnumeric1.8LQ-SC-04 and SQ-B-04 read this column. Toxicity (boron).
drainage_classtext'moderately_well'LQ-W-01 and SQ-C-01 read this column. Drainage condition.
flood_ev_10yinteger—LQ-W-02 and SQ-C-02 read this column. Flood hazard.
waterlog_d_yinteger—LQ-W-04 and SQ-C-03 read this column. Waterlogging risk.
slope_pctnumeric0.7LQ-T-01 and SQ-D-01 read this column. Terrain (slope).
erosion_w_t_hanumeric—LQ-T-02 and SQ-D-02 read this column. Water erosion.
erosion_wind_t_hanumeric—LQ-T-03 and SQ-D-03 read this column. Wind erosion.
sand_encr_m_ynumeric0LQ-T-04 and SQ-D-04 read this column. Sand encroachment.
gddinteger4820LQ-C-02 and SQ-E-02 read this column. Thermal regime.
radiation_mjnumeric22.4LQ-C-03 and SQ-E-03 read this column. Radiation.
ep_protectedtext—EP. Protected area.
ev_rangelandtext—EV. Rangeland, forest and afforestation.
et_tenuretext—ET. Tenure.
ez_zoningtext—EZ. Zoning designation.
ex_conflictingtext—EX. Conflicting use.
eh_hazardtext—EH. Hazard designation.
aridity_idxnumeric—SQ-E-01. Moisture deficit (aridity).
lgp_daysinteger—SQ-E-04. Length of growing period.
texture_classtext'loamy_sand'SQ-A-05. Soil texture.
coarse_frag_pctnumeric—SQ-A-06. Coarse fragments.
caco3_pctnumeric—SQ-B-05. Calcium carbonate.
gypsum_pctnumeric—SQ-B-06. Gypsum content.
ph_h2onumeric8.7SQ-B-07. Soil pH.
frost_daysinteger—SQ-E-05. Frost risk.
etc_m3_hanumeric—SQ-F-01. Irrigation demand (ETc).
nutrient_req_idxnumeric—SQ-F-02. Crop nutrient requirement.
completenessreal0.72Populated fraction. Module confidence is SQRT(governing × completeness).
wat_source_idsmallintFK412→ src.water_source. The selected source — the one that produced the water class.
source_typetext'renewable_groundwater_well'WP-A-01.
licensed_vol_m3_hanumeric(9,1)5445.0WP-A-02. Licensed abstraction ÷ service area. Not physical availability.
dist_source_kmnumeric(6,2)2.28WP-A-03.
level_trend_m_ynumeric(5,2)-1.80WP-B-01.
aquifer_typetext'fossil'WP-B-02.
supply_horizon_ysmallint6WP-B-03.
ecw_ds_mnumeric(6,2)3.10WP-C-01.
sarnumeric(5,2)7.40WP-C-02. Classed jointly with ecw_ds_m — see thr.class_range.
chloride_mg_lnumeric(7,1)420.0WP-C-03.
boron_w_mg_lnumeric(5,2)0.90WP-C-04.
ww_tiertextNULLWP-C-05. NULL unless the source is treated wastewater.
pump_lift_msmallint113WP-D-01.
conveyance_kmnumeric(6,2)2.28WP-D-02. Network distance, not Euclidean.
basin_yield_mm3numeric(9,1)88.0WP-E-01. Basin-level — every cell in a basin shares it.
alloc_pctnumeric(5,1)142.0WP-E-02. Above 100 means over-allocated.
wat_alternativesjsonb'[{"source_id":412,…}]'Other sources that could serve this hectare. Informational only — never classified, never joined to a threshold, never filtered on the map. NULL on almost every cell. This is the scalar/context line: scalar columns for anything the methodology rates, JSON for anything that is context.
cap_governingtextFK'LQ-SP-03'Materialised for filtering. “Show everything limited by salinity” cannot be reached from a measurement column.
wat_governingtextFK'WP-C-01'As above, for water.
cap_confreal0.66Materialised. “Show only high-confidence cells”.
wat_confrealNULLAs above.
any_fragilebooleanFALSEMaterialised. TRUE where any element sits within 1σ of a class boundary.
cap_class_idsmallintFK3The capability answer. Materialised because every map tile filters on it and MAX(rank) across 33 elements cannot be computed per tile at 215 M cells.
cap_subclasschar(1)'s'The limitation letter.
wat_class_idsmallintFKNULLThe water answer. NULL until thresholds exist.
wat_subclasschar(1)NULL
leg_class_idsmallintFK0The land rights answer. 0 is E0 — unknown, never clear.
leg_causetextFK'EP'Which check produced it.
cap_completenessreal0.72Populated fraction of the module. Module confidence is SQRT(governing × completeness).
wat_completenessreal0.00
computed_attimestamptz'2026-08-14 09:14+03'When the four answers were last materialised. Measurements carry no version; results do.
thr
Thresholds
Versioned class intervals. Supersession sets effective_to; rows are never deleted.
4 tables
46 columns
thr.versionEvery threshold set is versioned. Versions are immutable once superseded; supersession sets effective_to rather than deleting.10 col~5▾
ColumnTypeKeySample dataDefinition
version_idsmallintPKNOT NULL1
labeltextUQNOT NULL'Makkah'v1.0-alues · v1.1-ecocrop · v2.0-saudi-calibrated
effective_fromdateNOT NULL'2026-01-15'When this set becomes the operational reference.
effective_todateNULLNULL while current. Set on supersession. Rows are never deleted.
statustextNOT NULL'under_review'LKP-30draft · under_review · approved · superseded
approved_bytext'Reviewer or committee of record'Reviewer or committee of record. NULL until status = 'approved'.
approval_datedate'2026-01-15'
basistextNOT NULL'Source of the values: 'ALUES 0'Source of the values: 'ALUES 0.2.1 / Sys et al. 1993' · 'FAO ECOCROP' · 'Saudi expert panel'
is_operationalbooleanNOT NULLTRUEFALSE for all current rows. No version has been approved for national use.
notetext'Carried from the Al Lith pilot'Change summary against the preceding version.
thr.class_rangeOne or two dimensional. Class intervals for capability, water and land_rights elements. One row per element per class.13 col~350▾
ColumnTypeKeySample dataDefinition
band_idintegerPKNOT NULL2
version_idsmallintFKNOT NULL1→ thr.version
element_codetextFKNOT NULL'LQ-SP-03'LKP-06→ ref.element
class_idsmallintFKNOT NULL4LKP-03→ ref.class. The class this range produces.
value_lonumeric25.0Lower bound, inclusive. NULL for an unbounded lower interval.
value_hinumeric50.0Upper bound, exclusive. NULL for an unbounded upper interval.
value_settext[]'{a,b}'Enumerated member values for categorical elements, e.g. USDA texture codes.
is_stepbooleanNOT NULLTRUETRUE where value_lo = value_hi across all classes: a single cut-point rather than a graded interval set.
source_reftext'FAO (1976) Bulletin 32'FK to the reference register, e.g. LE-02, CR-02.
source_pagetext'p. 41'Page or table in the cited publication. NULL until original-source verification is complete.
co_element_codetextFK'WP-C-01'Optional second element the range is evaluated against. NULL for every one-dimensional range. Used by WP-C-02 only: FAO-29 assesses infiltration hazard from SAR and ECw jointly, because at a given SAR the infiltration rate improves as salinity rises.
co_value_lonumeric0.7Lower bound on the second element, inclusive. NULL where co_element_code is NULL.
co_value_hinumeric3.0Upper bound on the second element, exclusive. A row matches only when both the primary and the second value fall inside their bounds.
thr.crop_requirementPer-crop threshold intervals. Loaded from ALUES (1,268 rows) and ECOCROP-derived ranges.16 col~1,300▾
ColumnTypeKeySample dataDefinition
req_idintegerPKNOT NULL1
version_idsmallintFKNOT NULL1→ thr.version
crop_idintegerFKNOT NULL17LKP-12→ crop.crop
element_codetextFKNOT NULL'LQ-SP-03'LKP-06→ ref.element. Suitability elements only.
system_idsmallintFK1LKP-07→ ref.production_system. NULL where the threshold applies to all production systems.
s3_anumeric12.5Outer marginal limit, low side. ALUES field name retained for source traceability.
s2_anumeric12.5Moderate limit, low side.
s1_anumeric12.5Optimal limit, low side.
s1_bnumeric12.5Optimal limit, high side. NULL for single-sided parameters.
s2_bnumeric12.5Moderate limit, high side.
s3_bnumeric12.5Outer marginal limit, high side.
weightsmallint0.000.00–1.00ALUES importance weight 1–3. Retained for source fidelity. NOT referenced by any classification routine — assignment uses maximum limitation, not weighted aggregation.
is_two_sidedbooleanNOT NULLFALSETRUE where the element has a bounded optimum with limits on both sides, e.g. soil pH.
source_systemtextNOT NULL'ALUES_0.2.1'LKP-32ALUES_0.2.1 · FAO_ECOCROP · SAUDI_CALIBRATION
source_reftext'FAO (1976) Bulletin 32'FK to the reference register.
validation_statustextNOT NULL'source_validated'LKP-14extracted · source_validated · expert_reviewed · operational
thr.element_applicability64 elements × 8 production systems. Element applicability by production system. 66 × 8 cardinality.7 col512▾
ColumnTypeKeySample dataDefinition
app_idintegerPKNOT NULL164 elements × 8 systems.
version_idsmallintFKNOT NULL1→ thr.version
element_codetextFKNOT NULL'LQ-SP-03'LKP-06→ ref.element
system_idsmallintFKNOT NULL1LKP-07→ ref.production_system
markchar(1)NOT NULL'G'LKP-31G governs · N does not apply · Q qualifies (inverted) · C conditional
rationaletext'Model prediction, error unknown locally'Basis for the mark where not self-evident.
is_derivedbooleanNOT NULLTRUETRUE where derived from thr.crop_requirement; FALSE where provisional.
crop
Crop Library
Crop register (63 rows) and ECOCROP ecological profiles (7 rows).
2 tables
44 columns
crop.cropThe 63-crop register. One row per crop. Version-independent.12 col63▾
ColumnTypeKeySample dataDefinition
crop_idintegerPKNOT NULL17
internal_codetextUQNOT NULL1DATEPALM · WHEAT · TOMATO. Natural key. Stable across all published output.
common_name_entextNOT NULL'common name en'
common_name_artext'common name ar'
scientific_nametext'Phoenix dactylifera'Phoenix dactylifera. NULL where ECOCROP mapping is incomplete.
sci_name_verifiedbooleanNOT NULLTRUEFALSE where the name was supplied for reference rather than extracted from a source record.
crop_grouptextNOT NULL'Cereal'LKP-11Fruit · Cereal · Vegetable · Pulse · Forage · Oilseed · Root and tuber
ecocrop_idinteger1FAO ECOCROP identifier. Populated for 7 rows; NULL for 56 pending mapping.
alues_codetext1ALUES dataset code. Present for 56.
saudi_prioritybooleanNOT NULLTRUETRUE for the 7 crops holding a complete profile.
ksa_relevancetext'Contextual note for UI display'Contextual note for UI display.
operational_statusbooleanNOT NULLTRUEFALSE for all 63 rows. Requires thr.version.status = 'approved'.
Seeded values
63 values, not seeded here. The crop register is held in ALUES 0.2.1 and the FAO ECOCROP profiles, and is loaded from those sources rather than typed. 7 of the 63 carry full ECOCROP profiles; the remaining 56 have threshold records only.
crop.profileThe full FAO ECOCROP ecological profile. One row per crop holding a profile. Currently 7 of 63.32 col7▾
ColumnTypeKeySample dataDefinition
crop_idintegerPKFKNOT NULL17→ crop.crop
life_formtext'tree'tree · herb · shrub · grass
physiologytext'perennial'perennial · annual · biennial
life_spantext'life span'
temp_opt_min_cnumeric12.5Optimal temperature range, lower bound.
temp_opt_max_cnumeric12.5
temp_abs_min_cnumeric12.5Absolute survival range. CHECK constraint: abs interval must contain opt interval. Violation indicates a source error.
temp_abs_max_cnumeric12.5
rain_opt_min_mmnumeric12.5Annual rainfall, optimal.
rain_opt_max_mmnumeric12.5
rain_abs_min_mmnumeric12.5
rain_abs_max_mmnumeric12.5
ph_opt_minnumeric12.52.0–11.0Soil reaction, optimal range.
ph_opt_maxnumeric12.52.0–11.0
ph_abs_minnumeric12.52.0–11.0
ph_abs_maxnumeric12.52.0–11.0
soil_depth_opttext'Categorical: shallow · medium · deep'Categorical: shallow · medium · deep
soil_texture_opttext'USDA classes accepted at optimum'USDA classes accepted at optimum.
soil_fertility_opttext'soil fertility opt'
soil_salinity_opttext'soil salinity opt'
soil_drainage_opttext'soil drainage opt'
light_opttext'shaded'shaded · partial · bright
altitude_max_minteger10–5000 m
killing_temp_rest_cnumeric12.5Lethal temperature during dormancy. Input to SQ-E-05.
killing_temp_early_cnumeric12.5Lethal temperature during early growth. Differs materially from the dormant value, which is why frost is a separate element from thermal accumulation.
cycle_min_dayssmallint10–3650
cycle_max_dayssmallint10–3650
photoperiodtext'photoperiod'
climate_zonestext'climate zones'
critical_gapstext'Outstanding items blocking operational'Outstanding items blocking operational status.
source_urltext'Direct ECOCROP datasheet link'Direct ECOCROP datasheet link.
source_checkeddate'2026-01-15'
res
Results
Computed class assignments and aggregates. Every row records its governing element.
3 tables
35 columns
res.hectare_resultThe three crop-independent verdicts per cell. One row per cell per threshold version.16 col~215 M▾
ColumnTypeKeySample dataDefinition
cell_idbigintPKFKNOT NULL20700041832
version_idsmallintPKFKNOT NULL1
province_idsmallintPARTNOT NULL'02'LKP-33
cap_class_idsmallintFK4LKP-03→ ref.class. Null where completeness is too low to classify.
cap_subclasstext's'LKP-04Letters of the governing group(s), e.g. 'nz'.
cap_governingtext[]'LQ-SP-03'LKP-06Element codes that produced the class. Plural where they tie.
wat_class_idsmallintFK2LKP-03
wat_subclasstext'y'LKP-04
wat_governingtext[]'WP-B-01'LKP-06
wat_source_idintegerFK3Which of the cell’s water sources produced the published class. Without it the water class cannot be interpreted — a hectare can be W3 on groundwater and W1 on a desalination connection.
leg_class_idsmallintFK0LKP-03
leg_causetext[]'{a,b}'Check codes causing E2 or E3. Empty for E1.
composite_codetext'C4s'C2nz · W2qy · E2(ET). Materialised for display and export.
gates_passedsmallintNOT NULL10–3. How many of capable, watered, permitted are satisfied.
confidencetextNOT NULL0.79LKP-10high · medium · low · very_low. Same four bands as conf.result_confidence.band — a single vocabulary, not a parallel one. Denormalised here for display.
computed_attimestamptzNOT NULL'2026-03-02 09:14:22+03'
res.zone_cropCrop verdicts attached to zones as attributes. Zones are crop-agnostic; this is where crops attach.9 colzones × crops × systems▾
ColumnTypeKeySample dataDefinition
zone_idtextPKFKNOT NULL4182→ geo.zone
crop_idintegerPKFKNOT NULL17LKP-12
system_idsmallintPKFKNOT NULL1LKP-07
version_idsmallintPKFKNOT NULL1
class_idsmallintFKNOT NULL4LKP-03Modal or worst class across member cells — rule stated in the zoning method.
subclasstext'n'LKP-04
governing_elementtextFK'SQ-B-04'LKP-06
cell_agreement_pctsmallintNOT NULL870–100Share of member cells sharing this class. Low agreement signals a zone that should have split.
meets_min_areabooleanNOT NULLTRUEWhether the zone exceeds the minimum viable area for this production system.
res.area_ledgerThe study's headline output. Area by category, produced at each tier.10 col~pending▾
ColumnTypeKeySample dataDefinition
ledger_idintegerPKNOT NULL1
tiertextNOT NULL'governorate'LKP-27nation · province · governorate
tier_idinteger1Null at national tier.
system_idsmallintFKNOT NULL1LKP-07One ledger per production system — minimum viable area differs.
version_idsmallintFKNOT NULL1
categorytextNOT NULL'marginal'LKP-26ready · blocked_paperwork · blocked_water · marginal · not_developable
zone_countintegerNOT NULL38≥ 0
area_hanumericNOT NULL1504.75≥ 0
share_pctnumericNOT NULL2.40–100Of assessment area, not of total national area.
computed_attimestamptzNOT NULL'2026-03-02 09:14:22+03'
src
Provenance
Source register and element-to-source mapping. origin discriminates external from ministry-supplied.
3 tables
31 columns
src.data_sourceEvery input dataset. The origin column splits derivable from ministry-supplied — the project's critical path.16 col~35▾
ColumnTypeKeySample dataDefinition
source_idsmallintPKNOT NULL3
codetextUQNOT NULL'SOILGRIDS_250'SOILGRIDS_250 · SENTINEL2_L2A · ERA5_LAND · NCW_PROTECTED · WATHEEQ
name_entextNOT NULL'SoilGrids 2.0'
providertextNOT NULL'ISRIC · ESA Copernicus · ECMWF · NCW ·'ISRIC · ESA Copernicus · ECMWF · NCW · Ministry of Justice
origintextNOT NULL'external'LKP-15external — acquirable by the project · ministry — only MEWA or a partner authority can supply it.
authority_idsmallintFK2LKP-09→ ref.authority. Populated for ministry-origin sources.
licencetext'CC-BY 4.0'LKP-17CC-BY 4.0 · Copernicus open · restricted · not_yet_agreed
native_resolutiontext'250 m · 10 m · 0'250 m · 10 m · 0.1° · vector
native_sridinteger1
currencytext'Reference date or release version of t'Reference date or release version of the data.
update_cycletext'static'LKP-19static · annual · 5-day revisit · on_request
coveragetextNOT NULL'global'LKP-20global · regional · national · partial
access_routetext'API'LKP-18API · bulk download · formal request · MoU required
acquisition_statustextNOT NULL'not_started'LKP-16held · requested · negotiating · not_started · blocked
blocking_notetext'What is preventing acquisition, for mi'What is preventing acquisition, for ministry sources.
known_limitationstext'Cloud cover · coarse resolution · inco'Cloud cover · coarse resolution · incomplete national coverage · currency.
src.element_sourceWhich source feeds which element, and how. The provenance backbone — every value traces to a row here.9 col~90▾
ColumnTypeKeySample dataDefinition
link_idintegerPKNOT NULL1
element_codetextFKNOT NULL'LQ-SP-03'LKP-06→ ref.element
source_idsmallintFKNOT NULL3→ src.data_source
prioritysmallintNOT NULL11 = primary. 2+ = fallback where the primary has gaps.
derivationtextNOT NULL'model'LKP-21direct · index · model · proxy · lookup
derivation_chaintext'SoilGrids bdricm + cfvo → effective depth'The processing steps, e.g. 'Sentinel-2 B8,B4 → NDVI → 10-year max composite → 1.5 ha mean'.
processing_notetext'median composite 2019–2024, SCL + AOT masked'Resampling, compositing, gap-filling and cloud handling applied.
expected_confidence_notetext'medium'Advisory only. Recorded when the pairing is registered. Not read by any computation — the operative value is derived in conf.element_confidence. Kept textually distinct so a hand-entered expectation can never be mistaken for a computed score.
is_operationalbooleanNOT NULLTRUEFalse where the source is not yet held.
src.source_setA named combination of sources used for one processing run. Lets a result be tied to exactly what produced it.6 col~10▾
ColumnTypeKeySample dataDefinition
source_set_idsmallintPKNOT NULL2
labeltextUQNOT NULL'Makkah'run-2026-01-national · run-2026-03-makkah
run_datedateNOT NULL'2026-01-15'
scopetextNOT NULL'national'LKP-27national · province · governorate
source_idssmallint[]NOT NULL1Exactly which source versions were used.
notetext'Baseline national set'
conf
Confidence
Reliability scoring. Five tables holding the multiplier configuration, the per-element and per-cell component values, and the aggregation to module and zone level. All four component values are persisted alongside the combined score, which is what allows a revision to one component to be recomputed without reprocessing the others. The model these tables implement — the four components, the formula and the governing-element rule — is documented in the Confidence Scoring module.
4 tables
41 columns
conf.componentMultiplier configuration for the four confidence components. Reference data, not observations.8 col~30▾
ColumnTypeKeySample dataDefinition
component_idsmallintPKNOT NULL1
factortextNOT NULL2method | resolution | threshold_status.
keytextFKNOT NULL'satellite_modelled'LKP-13→ ref.domain_value. Enumerated key within the factor, e.g. field_measured, satellite_modelled, source_validated. The vocabulary is defined once in ref.domain_value; this table supplies only its multiplier.
scorenumeric(3,2)NOT NULL0.700.00–1.000.00–1.00 multiplier applied when the key matches.
definitiontextNOT NULL'How the value came into existence'What the key means, for UI display.
exampletext'A representative element and source fo'A representative element and source for this key.
rationaletextNOT NULL'Model prediction, error unknown locally'Basis for the assigned score. Required for audit.
is_activebooleanNOT NULLTRUEFALSE retains superseded scores without deleting the row.
conf.element_confidenceConfidence attributable to the element-source pairing. Invariant across cells; computed once per pairing.10 col~90▾
ColumnTypeKeySample dataDefinition
element_codetextPKFKNOT NULL'LQ-SP-03'LKP-06→ ref.element
source_idsmallintPKFKNOT NULL3→ src.data_source
methodtextNOT NULL'satellite_modelled'LKP-13How the value is obtained: field_measured | ministry_record | satellite_direct | satellite_modelled | inferred.
method_scorenumeric(3,2)NOT NULL0.700.00–1.00Multiplier from conf.component for the method. field_measured 1.00 → inferred 0.55.
res_scorenumeric(3,2)NOT NULL0.680.35–1.001.00 where source GSD ≤ cell width (107.46 m); otherwise 1/(1 + 0.5·log₂(GSD/w)), floored at 0.35.
source_confnumeric(3,2)NOT NULL0.690.00–1.00SQRT(method_score × res_score). Upper bound on confidence for this element-source pairing.
expected_errornumeric6.0≥ 0Source RMSE in the element's native unit. REQUIRED — boundary_conf cannot be computed without it.
error_basistext'Provenance of expected_error: publishe'Provenance of expected_error: publisher_rmse | cross_validation | field_comparison | expert_estimate.
field_sample_ninteger0≥ 0Count of field observations available for this element nationally. Zero for most; drives the field-validation programme.
last_revieweddate'2026-01-15'Date the pairing was last assessed.
conf.result_confidenceConfidence in the module-level class. Derived from the governing element, consistent with the maximum-limitation assignment rule.12 col~215 M▾
ColumnTypeKeySample dataDefinition
cell_idbigintPKFKNOT NULL20700041832
module_idsmallintPKFKNOT NULL1LKP-01→ ref.module. One row per cell per module.
version_idsmallintPKFKNOT NULL1
province_idsmallintPARTNOT NULL'02'LKP-33
governing_confnumeric(3,2)NOT NULL0.700.00–1.00Confidence of the element that determined the class; MIN() where multiple elements tie at the governing class. Not an aggregate across all elements — the class derives from one element, so its confidence derives from the same element.
completenessnumeric(3,2)NOT NULL190.00–1.00COUNT(non-null elements) / COUNT(module elements). A class computed from a partial element set is qualified by this ratio.
mean_confnumeric(3,2)NOT NULL0.780.00–1.00AVG(confidence) across all module elements. Stored for diagnostic comparison; not the published value.
confidencenumeric(3,2)NOT NULL0.790.00–1.00SQRT(governing_conf × completeness). The published value.
bandtextNOT NULL'medium'LKP-10high · medium · low · very_low
fragile_classbooleanNOT NULLFALSETRUE where sigma_to_boundary < 1.0 for the governing element. Indicates the class assignment is not stable under source error.
alt_class_idsmallintFK3LKP-03→ ref.class. The class the cell would take if the governing value moved one σ. Null where robust.
limiting_factortextNOT NULL'LQ-SC-04'LKP-06Component with the lowest score: resolution | derivation | validation | boundary | threshold | completeness. Aggregated, identifies the dominant constraint on output quality.
conf.zone_confidenceZone-level aggregation of cell confidence, including internal class agreement.11 col~pending▾
ColumnTypeKeySample dataDefinition
zone_idtextPKFKNOT NULL4182→ geo.zone
module_idsmallintPKFKNOT NULL1LKP-01
version_idsmallintPKFKNOT NULL1
mean_confnumeric(3,2)NOT NULL0.780.00–1.00Mean cell confidence across members.
min_confnumeric(3,2)NOT NULL0.640.00–1.00Worst cell in the zone.
p10_confnumeric(3,2)NOT NULL0.680.00–1.00P10 of member cell confidence. Less sensitive to a single outlier than MIN().
cell_agreementnumeric(3,2)NOT NULL0.870.00–1.00Share of member cells carrying the zone's class. Below ~0.90 suggests the zone should have been split.
fragile_sharenumeric(3,2)NOT NULL0.120.00–1.00COUNT(cells with fragile_class = TRUE) / cell_count.
confidencenumeric(3,2)NOT NULL0.790.00–1.00SQRT(p10_conf × cell_agreement). The published value.
bandtextNOT NULL'medium'LKP-10
recommendationtext'Remediation required to raise confiden'Remediation required to raise confidence: field_sampling | finer_imagery | threshold_approval | ministry_data.
wx
Weather
Meteorological history, forecast and long-term normals. Stored per source pixel, never per cell — one ERA5-Land pixel covers 8,100 hectare cells, and storing per cell would fabricate 8,100 identical rows and invite them to be treated as independent observations. Daily over ten years is 97 M rows per pixel-grid against 784,000 M per cell. Weather carries no class and no confidence score: it sits outside the assessed elements and is the retained input behind five of them.
5 tables
45 columns
wx.gridThe source pixels themselves. Weather is stored per pixel, never per cell.6 col~26,500▾
ColumnTypeKeySample dataDefinition
wx_grid_idintegerPKNOT NULL412
source_idsmallintFKNOT NULL7→ src.data_source. ERA5-Land, CHIRPS or an NCM station.
native_res_minteger9000Pixel size. NULL for a point station.
centroid_latnumeric(8,5)NOT NULL21.42120
centroid_lonnumeric(8,5)NOT NULL40.18730
geomgeometry(Polygon,4326)'Polygon(...)'The pixel footprint. Used to assign cells to grid pixels once, at load.
wx.variableWhat is recorded. A lookup, not a measurement table.6 col8▾
ColumnTypeKeySample dataDefinition
variable_idsmallintPKNOT NULL3
codetextUQNOT NULL'tp_mm't2m_mean · t2m_min · t2m_max · tp_mm · rh_pct · ws10m · ssrd_mj · et0_mm
name_entextNOT NULL'Precipitation'
name_artext'الأمطار'Draft, pending the Arabic glossary.
unit_idsmallintFK6→ ref.unit.
is_forecastablebooleanNOT NULLTRUEFALSE for variables the forecast model does not produce.
wx.observationThe history. RANGE-partitioned by year.11 col~97 M▾
ColumnTypeKeySample dataDefinition
wx_grid_idintegerPKFKNOT NULL412
obs_datedatePKNOT NULL'2024-07-14'Partition key.
t2m_meannumeric(4,1)33.8°C
t2m_minnumeric(4,1)28.9°C
t2m_maxnumeric(4,1)38.7°C
tp_mmnumeric(6,2)0.20mm
rh_pctnumeric(4,1)62.0%
ws10mnumeric(4,1)4.5m/s
ssrd_mjnumeric(5,2)22.40MJ/m²/day
et0_mmnumeric(5,2)8.60FAO-56 Penman-Monteith reference evapotranspiration.
source_idsmallintFKNOT NULL7
wx.forecastThe outlook. Two time keys, never one.11 col~155 M / yr▾
ColumnTypeKeySample dataDefinition
wx_grid_idintegerPKFKNOT NULL412
issued_attimestamptzPKNOT NULL'2026-08-05 00:00+03'When the run was made. Without it there is no way to say what was known when.
valid_datedatePKNOT NULL'2026-08-12'The day being forecast.
lead_dayssmallint7Generated from valid_date minus issued_at.
t2m_minnumeric(4,1)29.1
t2m_maxnumeric(4,1)38.4
tp_mmnumeric(6,2)0.00
rh_pctnumeric(4,1)64.0
ws10mnumeric(4,1)5.1
modeltextNOT NULL'ECMWF-IFS 48r1'The forecast system and its version.
supersededbooleanNOT NULLFALSETRUE once a later run covers the same valid_date. Keeps the current view simple without discarding history.
wx.normalLong-term monthly climatology. This is what the interface charts.11 col~318,000▾
ColumnTypeKeySample dataDefinition
wx_grid_idintegerPKFKNOT NULL412
monthsmallintPKNOT NULL71–12. CHECK BETWEEN 1 AND 12.
baseline_fromsmallintNOT NULL1991Stated on every chart axis. A normal without its baseline period is not interpretable.
baseline_tosmallintNOT NULL2020
t2m_meannumeric(4,1)33.8
t2m_minnumeric(4,1)28.9
t2m_maxnumeric(4,1)38.7
tp_mmnumeric(6,2)0.20
rh_pctnumeric(4,1)62.0
ws10mnumeric(4,1)4.5
ssrd_mjnumeric(5,2)22.40
How a measurement becomes a class

The Tables tab states that rooting_depth_cm accepts 0–300. It does not state that 42 cm is C4. That mapping is this table — thr.class_range — and without it a developer can store a valid measurement and still not know how to evaluate the land.

All four modules appear below, and they do not have the same shape. Capability has one numeric range per class per element. Water quality has three published tiers rather than five classes. Land rights has no numeric ranges at all — the class comes from a register state. Suitability has ranges that vary by crop, so they cannot be shown in a single row.

Each row is one element. Each cell is the interval of the measurement that yields that class. Intervals cannot overlap: an EXCLUDE constraint on numrange(value_lo, value_hi) per element per version prevents two classes claiming one value. Direction matters — the arrow beside each unit shows it. ↑ means higher is better, so C1 sits at the top of the range; ↓ means lower is better, so C1 sits at the bottom.

Table and column are given for every element so a developer can go straight from a class range to the attribute it tests. They are not hard-coded in the classification routine — they are read from ref.element.storage_table and ref.element.storage_column at run time, and the values shown here are those catalogue entries.

These are illustrative class ranges carried from the Al Lith pilot, not calibrated national thresholds. Every row below is registered for expert calibration and no version has yet been approved. Threshold version v1.0-alues stands at under_review, maturity source_validated, which is what caps confidence component 4 at 0.80 on every output in the study. A developer should read the structure as final and the numbers as provisional.

Capability — 17 elements, five classes each

ElementNameTableColumnUnitC1C2C3C4CN
LQ-SP-01Available water capacityobs.capabilityawc_mm_mmm/m ↑> 12090–12060–9030–60< 30
LQ-SP-02Soil workabilityobs.capabilityworkability_idxindex ↑> 8060–8040–6020–40< 20
LQ-SP-03Rooting conditionsobs.capabilityrooting_depth_cmcm ↑> 10075–10050–7525–50< 25
LQ-SP-04Surface sealing & crustingobs.capabilitysealing_idxindex ↑> 8060–8040–6020–40< 20
LQ-SC-01Salinity (ECe)obs.capabilityece_ds_mdS/m ↓< 22–44–88–16> 16
LQ-SC-02Sodicity (ESP)obs.capabilityesp_pct% ↓< 1010–1515–2525–40> 40
LQ-SC-03Nutrient availabilityobs.capabilitynutrient_idxindex ↑> 7050–70———
LQ-SC-04Toxicity (boron)obs.capabilityboron_mg_lmg/L ↓< 22–44–88–12> 12
LQ-W-01Drainage conditionobs.capabilitydrainage_classindex ↑> 7555–7535–5518–35< 18
LQ-W-02Flood hazardobs.capabilityflood_ev_10yevents/10 yr ↓< 11–22–44–7> 7
LQ-W-04Waterlogging riskobs.capabilitywaterlog_d_ydays/yr ↓< 1010–2525–5050–90> 90
LQ-T-01Terrain (slope)obs.capabilityslope_pct% ↓< 22–55–1010–16> 16
LQ-T-02Water erosionobs.capabilityerosion_w_t_hat/ha/yr ↓< 55–1010–2525–50> 50
LQ-T-03Wind erosionobs.capabilityerosion_wind_t_haindex ↓< 2020–4040–6060–80> 80
LQ-T-04Sand encroachmentobs.capabilitysand_encr_m_ym/yr ↓< 11–33–66–12> 12
LQ-C-02Thermal regimeobs.capabilitygdd°C·day ↑> 25001800–25001200–1800800–1200< 800
LQ-C-03Radiationobs.capabilityradiation_mjMJ/m²/day ↑—————
5 of the 85 cells are not yet seeded. LQ-C-03 Radiation has no class ranges recorded in any delivered module, and LQ-SC-03 Nutrient availability has only C1 and C2. They are shown empty rather than filled by interpolation, because a range invented to complete a table is indistinguishable from a calibrated one once it is in the database.

What the classification routine does with this table

One query per element, resolved from the catalogue rather than hard-coded:

-- 1. resolve where the value lives, from the catalogue
SELECT storage_table, storage_column
FROM   ref.element WHERE element_code = 'LQ-SP-03';
--     obs.capability | rooting_depth_cm

-- 2. read the value and find the range containing it
SELECT r.class_id
FROM   thr.class_range r
WHERE  r.element_code = 'LQ-SP-03'
  AND  r.version_id   = 1
  AND  42.0 >= r.value_lo AND 42.0 < r.value_hi;   -- → C4

Then MAX(rank) across the 19 results gives the cell class, and the element holding that rank is flagged is_governing. No averaging, no weighting: the worst-rated element decides, and it is named.

Water quality — what FAO-29 actually supports

Ayers & Westcot (1985), Water Quality for Agriculture, FAO Irrigation and Drainage Paper 29 Rev. 1, gives interpretation guidelines for irrigation water. It publishes three degrees of restriction, not five. The tiers are reproduced below in the source’s own structure rather than redistributed across W0–W4.
ElementParameterTableColumnUnitNoneSlight to moderateSevereSource
WP-C-01Irrigation water salinity (ECw)obs.cellecw_ds_mdS/m ↓< 0.70.7–3.0> 3.0FAO-29 Table 1
WP-C-03Chloride — surface irrigationobs.cellchloride_mg_lmg/L ↓< 142142–355> 355FAO-29 Table 1, converted from 4 and 10 me/L
WP-C-03Chloride — sprinkler irrigationobs.cellchloride_mg_lmg/L ↓< 106—> 106FAO-29 Table 1, converted from 3 me/L
WP-C-04Boronobs.cellboron_w_mg_lmg/L ↓< 0.70.7–3.0> 3.0FAO-29 Table 1
Three tiers cannot be mapped onto five classes without inventing two boundaries per parameter. FAO-29 gives the outer cut-points — 0.7 and 3.0 for ECw and boron, 4 and 10 me/L for chloride. Where the remaining W-class edges fall inside those intervals is not published, and interpolating them would produce numbers indistinguishable from calibrated ones once stored. The three tiers are recorded here as evidence; the W0–W4 assignment is registered for expert calibration.
WP-C-02 Sodium adsorption ratio cannot be divided into ranges on its own at all. FAO-29 evaluates SAR jointly with ECw for infiltration hazard — at a given SAR the infiltration rate rises as salinity rises, so an SAR of 6 is a problem at ECw 0.3 and not at ECw 1.2. A single-column range table cannot represent a two-variable surface. WP-C-02 needs either a two-dimensional lookup keyed on both values, or an explicit decision to assess infiltration as a derived element. This is a schema question, not a calibration question, and it should be resolved before the water module is built.

Length of growing period — FAO agro-ecological zones

The FAO agro-ecological zoning framework classifies LGP into five moisture zones. This is the one remaining capability gap with a published five-class structure that matches the C1–CN series.
ElementNameTableColumnUnitC1C2C3C4CN
Candidate, not delivered. These are the FAO AEZ moisture-zone boundaries — humid, sub-humid, moist semi-arid, dry semi-arid, arid. The class structure aligns, but the assignment of arid to CN would place most of the Kingdom in the terminal class on this element alone, which is very unlikely to be the intended reading and is exactly why calibration is required. Recorded at extracted maturity (0.65), below every other range in the study.

Land rights — no numeric ranges, and none should exist

The six legal checks are not measurements, so there is nothing to divide into ranges. E0–E3 is assigned directly from the state of a register, which is why all six columns are categorical. The table and column are given so the mapping can be wired once the registers arrive.
ElementNameTableColumnWhat determines the classRegister
EPProtected areaobs.land_rightsep_protectedDesignation category → permitted useNCW protected-area register
EVRangeland, forest and afforestationobs.land_rightsev_rangelandDesignation class → grazing or cultivation regimeNCVC rangeland and forest register
ETTenureobs.land_rightset_tenureRegistered · disputed · injunction · unrecordedMOJ Watheeq cadastre
EZZoning designationobs.land_rightsez_zoningLand-use class → whether agriculture is permittedMOMAH zoning scheme
EXConflicting useobs.land_rightsex_conflictingPresence of an overlapping designationMOE / MOD / MODON designations
EHHazard designationobs.land_rightseh_hazardHazard type and severity → development restrictionNCEC hazard mapping
The category-to-class mapping cannot be written yet. Assigning E1 rather than E2 depends on the designation categories each authority actually uses — which protected-area classes permit managed agriculture, which zoning classes bar it outright. Those category lists arrive with the registers themselves, as requests MD-04 to MD-07. Until then every hectare stands at E0, which denotes an unknown legal state and is never promoted to clear.

Suitability — 26 factors, ranges held per crop

Suitability ranges cannot appear in a table of this shape, because the same measurement is rated differently for each crop. A rooting depth of 42 cm is comfortable for barley and marginal for date palm. The ranges therefore live in thr.crop_requirement, keyed on crop_id as well as element_code — 1,268 records across 56 crops from ALUES 0.2.1. The 26 factors and the columns they read are below.
ElementFactorTableColumnUnitCapability refS1S2S3N
SQ-A-01Available water capacityobs.suitabilityawc_mm_mmm/m ↑LQ-SP-01————
SQ-A-02Soil workabilityobs.suitabilityworkability_idxindex ↑LQ-SP-02————
SQ-A-03Rooting conditionsobs.suitabilityrooting_depth_cmcm ↑LQ-SP-03per cropper cropper cropper crop
SQ-A-04Surface sealing and crustingobs.suitabilitysealing_idxindex ↑LQ-SP-04————
SQ-A-05Soil textureobs.suitabilitytexture_classcategory —LQ-SP-03per cropper cropper cropper crop
SQ-A-06Coarse fragmentsobs.suitabilitycoarse_frag_pct% ↓LQ-SP-03per cropper cropper cropper crop
SQ-B-01Salinity (ECe)obs.suitabilityece_ds_mdS/m ↓LQ-SC-01per cropper cropper cropper crop
SQ-B-02Sodicity (ESP / SAR)obs.suitabilityesp_pct% ↓LQ-SC-02————
SQ-B-04Toxicity risk (boron)obs.suitabilityboron_mg_lmg/L ↓LQ-SC-04per cropper cropper cropper crop
SQ-B-05Calcium carbonateobs.suitabilitycaco3_pct% ↓LQ-SC-03per cropper cropper cropper crop
SQ-B-06Gypsum contentobs.suitabilitygypsum_pct% ↓LQ-SC-03per cropper cropper cropper crop
SQ-B-07Soil pHobs.suitabilityph_h2opH ↔LQ-SC-03per cropper cropper cropper crop
SQ-C-01Drainage conditionobs.suitabilitydrainage_classindex ↑LQ-W-01————
SQ-C-02Flood hazardobs.suitabilityflood_ev_10yevents/10 yr ↓LQ-W-02————
SQ-C-03Waterlogging riskobs.suitabilitywaterlog_d_ydays/yr ↓LQ-W-04————
SQ-D-01Terrain workabilityobs.suitabilityslope_pct% ↓LQ-T-01per cropper cropper cropper crop
SQ-D-02Water erosion hazardobs.suitabilityerosion_w_t_hat/ha/yr ↓LQ-T-02————
SQ-D-03Wind erosion hazardobs.suitabilityerosion_wind_t_haindex ↓LQ-T-03————
SQ-D-04Sand encroachment hazardobs.suitabilitysand_encr_m_ym/yr ↓LQ-T-04————
SQ-E-01Moisture deficit (aridity)obs.suitabilityaridity_idxP/PET ↑ownper crop———
SQ-E-02Thermal suitabilityobs.suitabilitygdd°C·day ↑LQ-C-02per cropper cropper cropper crop
SQ-E-03Radiation and solar energyobs.suitabilityradiation_mjMJ/m²/day ↑LQ-C-03————
SQ-E-04Length of growing periodobs.suitabilitylgp_daysdays ↑ownper crop———
SQ-E-05Frost riskobs.suitabilityfrost_daysdays/yr ↓—per cropper cropper cropper crop
SQ-F-01Irrigation demand (ETc)obs.suitabilityetc_m3_hamm/season ↓—per cropper cropper cropper crop
SQ-F-02Crop nutrient requirementobs.suitabilitynutrient_req_idxkg/ha ↓—————
Eleven of the 26 carry a per-crop range in ALUES; the other fifteen do not. Where a factor has no crop-specific requirement it is rated against the same range as its capability reference, shown in the Capability ref column — so SQ-C-02 flood hazard uses the LQ-W-02 ranges above, and only SQ-A-03, SQ-B-01, SQ-B-04 and the eight others marked per crop vary by crop.

Resolving a suitability class takes one more key than a capability class.

SELECT r.class_id
FROM   thr.crop_requirement r
WHERE  r.element_code = 'SQ-A-03'
  AND  r.crop_id      = 17          -- the crop being tested
  AND  r.system_id    = 1           -- and the production system
  AND  r.version_id   = 1
  AND  42.0 >= r.value_lo AND 42.0 < r.value_hi;

A cell therefore carries one capability class and up to 63 suitability classes, one per crop in the library. This is why classify.crop_breakdown() is keyed on crop_id and system_id while res.hectare_result is not.

What cannot be completed, and why

LQ-C-03 RadiationNo published classification divides incoming radiation into agricultural capability classes. Radiation is used as an input to reference evapotranspiration in FAO-56, not as a classified limitation. Completing this row means creating the scheme, not sourcing it.
LQ-SC-03 Nutrient availabilityThe index has no defined construction, so there is nothing to divide into ranges. This is the gap identified on the six index-valued columns — the ranges cannot precede the definition of the scale.
WP-A, WP-B, WP-D, WP-E — 11 parametersAvailable volume, distance to source, water-level trend, supply horizon, pumping lift, conveyance distance, basin yield, allocation. These are policy thresholds, not physical ones. What counts as an acceptable decline rate or a viable pumping lift is a Saudi water-policy determination held by SWA and MEWA, and no international source can supply it.
Suitability — 26 factorsAlready sourced, but per crop rather than per element: 1,268 threshold records across 56 crops in ALUES 0.2.1, plus 7 full FAO ECOCROP profiles. They belong in thr.crop_requirement, not here.
The division this table rests on

Capability asks whether the land can carry the activity. Suitability asks what it will produce.

That means capability is evaluated per industry. The same hectare can be capable for aquaculture and not for an orchard, because the two activities ask different things of the ground. An element that has no meaning for an activity is marked N and takes no part in the class.

Suitability then splits by crop and production system and evaluates every factor, because at that point a crop has been named and every factor has a referent.

Three marks
A — AppliesMeasured, classed, and able to govern the cell under MAX(rank).
R — ReversedApplies, but the sign or the threshold is not the default. Requires its own range set. All five sit under aquaculture.
N — Does not applyExcluded from the class, from the element breakdown and from completeness. The element has no referent for this activity.

Capability — 17 elements across 8 industries

Can the land carry the activity? One class per hectare per industry. A cell marked • carries a note; hover to read it.
ElementNameIrrigated open
field
Orchard
permanent crop
Protected
cultivation
Rainfed
cropping
LivestockAquacultureAgro-
industry
Land
management
LQ-SP-01Available water capacity ▾AAAAAN•N•A
What it measures. How much water the soil can hold for plants between one watering and the next.
Why it matters. Water held in the soil is what carries a plant between one watering and the next. Where the soil holds little, the same crop needs more frequent irrigation for the same yield — so this element sets operating cost as much as it sets viability.
By industry
AOrchard / permanent crop. A tree cannot be replanted each season, so a soil that dries fast imposes a permanent irrigation burden rather than a seasonal one.
ARainfed cropping. Decisive. Without irrigation the soil store is the entire buffer between rainfall events.
ALivestock. Determines how long pasture holds after rain, and therefore stocking rate.
ALand management. Establishment survival for afforestation depends on it more than mature growth does.
LQ-SP-02Soil workability ▾AAN•AANN•A
What it measures. How easily the soil can be ploughed, tilled and worked with machinery.
Why it matters. Whether machinery can prepare the ground, and in what window. A soil workable only for a few days after rain constrains the whole operation, not just the ploughing.
By industry
AOrchard / permanent crop. Matters at establishment; after that the ground is rarely worked.
NProtected cultivation. Beds are prepared once and then managed by hand or by substrate. The seasonal tillage window does not arise.
ALivestock. Relevant only where forage is cultivated rather than grazed.
LQ-SP-03Rooting conditions ▾AAAAAN•N•A
What it measures. How deep roots can grow before they hit rock, hardpan or stone and stop.
Why it matters. How deep roots can go before rock or hardpan stops them. It sets which crops can establish at all, and it caps the soil water and nutrient store regardless of what is applied at the surface.
By industry
AOrchard / permanent crop. The binding element for tree crops. Date palm needs a metre; a shallow soil rules the activity out rather than reducing yield.
AProtected cultivation. Container and substrate systems reduce the dependence, but in-ground protected cultivation is as exposed as open field.
NAquaculture. There are no roots. Depth to rock matters for excavation, which is a construction question, not a capability one.
ALand management. Tree establishment depends on it; ground cover and grasses do not.
LQ-SP-04Surface sealing and crusting ▾AAN•AANN•A
What it measures. Whether the soil surface seals over and forms a crust after rain or irrigation.
Why it matters. Whether the surface seals into a crust after rain or irrigation. A sealed surface sheds water instead of absorbing it, and seedlings fail to break through.
By industry
NProtected cultivation. No rainfall reaches the surface, and irrigation is applied below the crust-forming energy threshold.
ARainfed cropping. Most acute here. Raindrop impact is the mechanism, and there is no irrigation to compensate for the water shed.
LQ-SC-01Salinity (ECe) ▾AAAAAR•N•A
What it measures. How salty the soil is. Salt draws water away from roots, so plants wilt even in moist soil.
Why it matters. Salt draws water away from roots, so a plant wilts in soil that is measurably moist. It is the single most widespread soil constraint in the Kingdom, and it is reclaimable where drainage and clean water exist.
By industry
AOrchard / permanent crop. A permanent planting cannot be moved when salinity rises, so the trend matters as much as the level.
AProtected cultivation. Controlled leaching manages it, but the enclosed root zone concentrates salt faster if drainage fails.
RAquaculture. Reversed. Brackish systems tolerate what a crop cannot, and some require salinity. The element applies; the direction does not.
ALand management. Salt-tolerant species exist, so a high reading narrows the palette rather than closing the option.
LQ-SC-02Sodicity (ESP) ▾AAAAAR•N•A
What it measures. How much sodium the soil holds. Sodium collapses soil structure, so water cannot drain through.
Why it matters. Sodium collapses soil structure, so water stops moving through. It is slower and more expensive to correct than salinity — gypsum followed by leaching, not leaching alone.
By industry
ARainfed cropping. Structure collapse is unrecoverable without irrigation water to leach with.
RAquaculture. Reversed. A sodic layer seals a pond floor, which is what pond construction is trying to achieve.
LQ-SC-03Nutrient availability ▾AAAAAN•N•A
What it measures. Whether the soil supplies the nutrients plants need without heavy fertiliser.
Why it matters. Whether the soil supplies nutrients without continuous fertiliser. It rarely closes an option outright, but it sets a running cost that compounds over the life of a planting.
By industry
AProtected cultivation. Fertigation supplies nutrients directly, so soil fertility becomes a minor input.
NAquaculture. Feed is supplied. The soil is a container, not a nutrient source.
ALand management. Non-productive planting tolerates low fertility that a crop would not.
LQ-SC-04Toxicity (boron) ▾AAAAAR•N•A
What it measures. How much boron is in the soil. A little is essential; slightly more is toxic to plants.
Why it matters. Boron is essential in traces and toxic just above them, and unlike salt it is very difficult to leach out. Treat a high reading as a permanent crop-selection constraint rather than a reclamation target.
By industry
AOrchard / permanent crop. A tree planted into toxic boron cannot be rotated out of it.
RAquaculture. Reversed. Boron toxicity thresholds are set for plants; stock and fish tolerances are different quantities.
LQ-W-01Drainage condition ▾AAAAAR•AA
What it measures. How well water drains away after rain or irrigation, rather than sitting around the roots.
Why it matters. Whether water leaves the root zone after irrigation or sits around it. Poor drainage starves roots of air, and it is also what makes salinity irreversible — there is nowhere for the salt to go.
By industry
AOrchard / permanent crop. Waterlogged roots kill a tree outright rather than reducing a season’s yield.
RAquaculture. Reversed. Poor drainage holds a pond. Free-draining ground is the defect, and lining it is the cost.
AAgro-industry. Site drainage governs foundations and hardstanding rather than root health.
LQ-W-02Flood hazard ▾AAAAAAAA
What it measures. How often this land floods, counted as events per decade.
Why it matters. How often the land floods. Flooding destroys a season’s crop, a permanent planting, or a building, and the consequence differs by activity more than the hazard does.
By industry
AOrchard / permanent crop. A flood event destroys years of establishment, not one season.
AAquaculture. A flood breaches ponds and releases stock.
AAgro-industry. Governs siting and insurance rather than production.
LQ-W-04Waterlogging risk ▾AAAAAR•AA
What it measures. How many days a year water stands on the surface, starving roots of air.
Why it matters. How many days a year water stands on the surface. Roots need air; extended standing water drowns them.
By industry
AProtected cultivation. The structure excludes surface water, but the enclosed root zone is less forgiving of what does accumulate.
RAquaculture. Reversed. Standing water is the objective, not the hazard.
LQ-T-01Terrain (slope) ▾AAAAAAAA
What it measures. How steep the land is. Steep ground is hard to irrigate evenly and hard to work.
Why it matters. How steep the ground is. Slope governs whether water can be applied evenly, whether machinery can work, and how much of what is applied stays where it was put.
By industry
AProtected cultivation. Structures need a level pad. Slope becomes an earthworks cost rather than an agronomic limit.
AAquaculture. Ponds require near-level ground; slope drives excavation volume directly.
AAgro-industry. A construction constraint. The same figure, a different consequence.
LQ-T-02Water erosion ▾AAAAAAN•A
What it measures. How much soil rainfall washes away each year.
Why it matters. How much soil rainfall carries away each year. It is the element where cultivation itself makes the problem worse, so a moderate reading under an intensive system is more serious than a high reading under cover.
By industry
ARainfed cropping. Most exposed. Bare soil between crops and no irrigation to establish cover quickly.
NAgro-industry. A sealed site does not erode.
ALand management. This is often the reason for the activity rather than a constraint on it.
LQ-T-03Wind erosion ▾AAN•AAAN•A
What it measures. How much soil the wind strips away each year, in tonnes per hectare.
Why it matters. How much soil the wind strips. Measured in the same unit as water erosion, so the two hazards can be compared and summed rather than argued about.
By industry
NProtected cultivation. The structure shelters the surface entirely.
ALivestock. Grazing pressure is what exposes the surface, so the hazard is partly a management variable.
NAgro-industry. A sealed site does not erode.
LQ-T-04Sand encroachment ▾AAAAAAAA
What it measures. How fast wind-blown sand is advancing across the land.
Why it matters. How fast wind-blown sand is advancing. Unlike erosion this arrives from elsewhere, so no on-site practice stops it — only shelterbelts and stabilisation, maintained indefinitely.
By industry
AOrchard / permanent crop. A permanent planting in the path of advancing sand is a permanent maintenance liability.
AProtected cultivation. Sand abrades and buries structures as readily as crops.
AAgro-industry. Burial of access roads and intakes is the failure mode.
LQ-C-02Thermal regime ▾AAN•AAAN•A
What it measures. How much usable warmth the growing season provides.
Why it matters. Whether the season supplies enough usable warmth. An absolute property of the location, true whatever is planted.
By industry
NProtected cultivation. The enclosure sets the thermal regime. The site’s own regime becomes an energy cost, not a limit.
AAquaculture. Water temperature governs species selection and growth rate.
NAgro-industry. Processing is not temperature-limited by the site.
LQ-C-03Radiation ▾AAN•AAN•N•A
What it measures. How much sunlight reaches the crop each day.
Why it matters. How much sunlight reaches the ground. Like thermal regime, an absolute site property rather than a crop-relative one.
By industry
NProtected cultivation. Supplemental lighting substitutes where the season is short, again at a cost.
NAquaculture. Radiation drives crop photosynthesis, not pond viability.
NAgro-industry. Not a production input.
Elements in play171712171711517
Three industries account for every exclusion. Agro-industry keeps 5 of 17 — a processing site is built on the land, not grown in it, so terrain, flood, sand drift and drainage remain and soil chemistry does not. Aquaculture keeps 11, of which 5 are reversed. Protected cultivation keeps 12: the structure supplies the thermal regime, the light and the shelter that the site would otherwise have to.

The other five industries — irrigated open field, orchard, rainfed, livestock and land management — use all 17. They differ in what they need from the land, not in which questions are worth asking of it.
The five reversed marks are the ones to check first. Each asserts that an element means the opposite for aquaculture than it does for a crop — poor drainage holds a pond, sodicity seals its floor, standing water is the objective. Each needs its own range set before an aquaculture class can be produced, and each is a claim an agronomist should either confirm or strike.

Suitability — every factor, per crop system

What will the land produce? Once a crop is named every factor has a referent, so all 26 apply. The variation lives in the thresholds, which are keyed on crop and system in thr.crop_requirement, not in whether a factor participates.
Irrigated open fieldAll 26 factors apply. Thresholds vary by crop; 14 of the 26 carry a crop-specific range.
Orchard / permanent cropAll 26 factors apply. Thresholds vary by crop; 14 of the 26 carry a crop-specific range.
Protected cultivationAll 26 factors apply. Thresholds vary by crop; 14 of the 26 carry a crop-specific range.
Rainfed croppingAll 26 factors apply. Thresholds vary by crop; 14 of the 26 carry a crop-specific range.
Livestock · Aquaculture
Agro-industry · Land management
No suitability class at all. These activities grow no crop, so a crop-suitability class has no referent. A cell under them carries a capability, water and legal class and no S code — which the interface must render as not applicable, never as N2.

What this costs the schema

Capability is no longer a single class per hectare. It varies by industry, so res.hectare_result.cap_class_id cannot hold it alone. A res.capability_system table is needed — one row per cell per industry — and res.hectare_result retains a single class for a nominated reference industry, stated explicitly.

This also touches zoning. Zone boundaries are drawn from capability, water, legal state and governorate. If capability varies by industry, zoning must nominate the same reference industry — almost certainly irrigated_open — and say so on the module. The alternative is a zone set per industry, which multiplies the area ledger by eight.

Both need a decision before the results schema is built.

How the routine reads it.

-- capability, for one industry
SELECT ec.element_code, ec.class_id, ec.rank
FROM   classify.element_breakdown($1,$2) ec
JOIN   thr.element_applicability a
         ON a.element_code = ec.element_code AND a.system_id = $2
WHERE  ec.cell_id = $1 AND a.mark <> 'N'      -- N takes no part
ORDER  BY ec.rank DESC;                        -- first row governs

-- suitability, for one crop under one system: no applicability filter
SELECT class_id FROM thr.crop_requirement
WHERE  crop_id = $1 AND system_id = $2 AND version_id = $3;

Capability filters on the matrix. Suitability does not, because every factor applies once a crop is named.

Every value a hectare can answer — 365 in total

A cell carries 70 stored columns and 295 values computed when it is opened. This page lists all of them: what each one is, whether it is stored or derived, and if derived, from what.

The distinction is the whole design. An input is a fact about the hectare, loaded by the ETL, independent of any threshold. A computed value is a judgement about that fact, and it changes the moment someone changes a threshold in the admin area. Storing judgements makes changing them expensive; storing facts does not.

The arithmetic
6 — keysIdentity, partition, version, provenance. Not measurements and not results.
50 — inputMeasured values. 33 for the cell, 16 for the selected water source, 1 jsonb for alternatives.
14 — computed, storedThe map filters on these across 215 M cells, so they are materialised.
295 — computed on read59 scorable elements × 5 values each. Never stored.
365 — totalWhat a cell can answer.

Keys and provenance — 6 stored

ColumnTypeKindWhat it isWhere it comes from
cell_idbigintkeyThe hectare. Encodes province, district, level and axial coordinates.Generated by the grid, not measured.
province_idsmallintkeyPartition key. 13 partitions.Decoded from cell_id.
version_idsmallintkeyWhich threshold version the stored results were computed under.Set by the classification run.
obs_datedatekeyReference date of the source, not the load date.From the source metadata. A 2020 SoilGrids value loaded in 2026 is a 2020 observation.
source_set_idintegerkeyWhich combination of sources produced this row.Set by the ETL run.
computed_attimestamptzkeyWhen the stored results were last materialised.Set by the classification run.

Input — 50 stored, measured

Facts about the hectare. No threshold is involved in producing any of these. Each is loaded by an ETL job from a named source; the Acquisition module gives the layer name and extraction steps for every one.
ColumnUnitElementWhat it measuresSource and how
awc_mm_mnumericLQ-SP-01 · SQ-A-01Available water capacity.SoilGrids 2.0 · wv0033 and wv1500
workability_idxnumericLQ-SP-02 · SQ-A-02Soil workability. Blocked — the method for computing it has never been defined.SoilGrids 2.0
rooting_depth_cmnumericLQ-SP-03 · SQ-A-03Rooting conditions.SoilGrids 2.0 · bdricm, constrained by cfvo
sealing_idxnumericLQ-SP-04 · SQ-A-04Surface sealing and crusting. Blocked — the method for computing it has never been defined.SoilGrids 2.0
ece_ds_mnumericLQ-SC-01 · SQ-B-01Salinity (ECe).GSASMAP + SENTINEL2_L2A · salt-affected class; B2 B3 B4 B8 B11
esp_pctnumericLQ-SC-02 · SQ-B-02Sodicity (ESP).Global Map of Salt-Affected Soils · sodic class
nutrient_idxnumericLQ-SC-03Nutrient availability. Blocked — the method for computing it has never been defined.SoilGrids 2.0
boron_mg_lnumericLQ-SC-04 · SQ-B-04Toxicity (boron).Global Lithological Map v1.0 · xx first-level lithology
drainage_classtextLQ-W-01 · SQ-C-01Drainage condition.Harmonized World Soil Database v2.0 · DRAINAGE field on HWSD2_LAYERS
flood_ev_10yintegerLQ-W-02 · SQ-C-02Flood hazard.JRC Global Surface Water · occurrence band
waterlog_d_yintegerLQ-W-04 · SQ-C-03Waterlogging risk.JRC Global Surface Water · seasonality band
slope_pctnumericLQ-T-01 · SQ-D-01Terrain (slope).Copernicus DEM GLO-30 · DEM elevation band
erosion_w_t_hanumericLQ-T-02 · SQ-D-02Water erosion.COP_DEM_GLO30 + SOILGRIDS_250 + CHIRPS · R, K, LS, C, P factors
erosion_wind_t_hanumericLQ-T-03 · SQ-D-03Wind erosion.ERA5_LAND + SOILGRIDS_250 · 10m wind components; sand fraction
sand_encr_m_ynumericLQ-T-04 · SQ-D-04Sand encroachment.Sentinel-2 MSI Level-2A · B8, B11, B12 bare-soil composite
gddintegerLQ-C-02 · SQ-E-02Thermal regime.ERA5-Land reanalysis · 2m_temperature
radiation_mjnumericLQ-C-03 · SQ-E-03Radiation.ERA5-Land reanalysis · surface_solar_radiation_downwards
ep_protectedtextEPProtected area.Protected area polygons · Protected area polygon, designation category and permitted-use attribute
ev_rangelandtextEVRangeland, forest and afforestation.Rangeland, forest and afforestation layer · Rangeland, forest and afforestation polygon with its designation class
et_tenuretextETTenure.Watheeq cadastral records · Parcel geometry, title status, dispute and injunction flags
ez_zoningtextEZZoning designation.Governorate boundaries and zoning schemes · Zoning scheme polygon and its land-use class
ex_conflictingtextEXConflicting use.Hazard designation and environmental constraint mapping · Petroleum, mining, military and industrial designation polygons
eh_hazardtextEHHazard designation.Hazard designation and environmental constraint mapping · Hazard designation polygon with type and severity
aridity_idxnumericSQ-E-01Moisture deficit (aridity).Global Aridity Index and PET v3 · ai_v3_yr
lgp_daysintegerSQ-E-04Length of growing period.ERA5-Land reanalysis · 2m_temperature
texture_classtextSQ-A-05Soil texture.SoilGrids 2.0 · sand, silt, clay
coarse_frag_pctnumericSQ-A-06Coarse fragments.SoilGrids 2.0 · cfvo
caco3_pctnumericSQ-B-05Calcium carbonate.Harmonized World Soil Database v2.0 · CACO3 on HWSD2_LAYERS
gypsum_pctnumericSQ-B-06Gypsum content.Harmonized World Soil Database v2.0 · GYPSUM on HWSD2_LAYERS
ph_h2onumericSQ-B-07Soil pH.SoilGrids 2.0 · phh2o
frost_daysintegerSQ-E-05Frost risk.ERA5-Land reanalysis · 2m_temperature minimum
etc_m3_hanumericSQ-F-01Irrigation demand (ETc).ERA5-Land reanalysis · ET₀ drivers
nutrient_req_idxnumericSQ-F-02Crop nutrient requirement.ALUES 0.2.1 threshold database · crop nutrient requirement
source_typetextWP-A-01Source type.Ministry register — not yet delivered. Well type / source classification
avail_vol_m3_hanumericWP-A-02Available volume.Ministry register — not yet delivered. Licensed annual abstraction, m³/yr, and the served area in ha
dist_source_kmnumericWP-A-03Distance to source.Ministry register — not yet delivered. Well coordinates
level_trend_m_ynumericWP-B-01Water-level trend.Ministry register — not yet delivered. Monitoring well time series, static water level by date
aquifer_typetextWP-B-02Aquifer type.Ministry register — not yet delivered. SGS hydrogeological unit polygon and its recharge classification
supply_horizon_ynumericWP-B-03Remaining supply horizon.Ministry register — not yet delivered. Saturated thickness and abstraction rate
ecw_ds_mnumericWP-C-01Irrigation water salinity.Ministry register — not yet delivered. Water quality analysis, EC at 25 °C
sarnumericWP-C-02Sodium adsorption ratio.Ministry register — not yet delivered. Na, Ca, Mg in meq/L
chloride_mg_lnumericWP-C-03Chloride.Ministry register — not yet delivered. Cl in mg/L
boron_w_mg_lnumericWP-C-04Boron in irrigation water.Ministry register — not yet delivered. B in mg/L
ww_tiertextWP-C-05Treated wastewater tier.Ministry register — not yet delivered. Treatment plant register, process level
pump_lift_mnumericWP-D-01Pumping lift.Ministry register — not yet delivered. Static water level
conveyance_kmnumericWP-D-02Conveyance distance.Ministry register — not yet delivered. Canal and pipeline network geometry
basin_yield_mm3numericWP-E-01Basin sustainable yield.Ministry register — not yet delivered. MEWA basin determination, Mm³/yr
alloc_pctnumericWP-E-02Allocation status.Ministry register — not yet delivered. Sum of licensed abstraction in the basin
wat_alternativesjsonb—Other sources that could serve this hectare. Never classified, never filtered nationally.Assembled from the water register. Context for one cell, not a rated value.

Computed and stored — 14

These are results, not measurements — but they are materialised, because the map filters on them across 215 M cells and no arrangement of the 50 inputs answers those filters without evaluating the whole comparison first. They are rewritten whenever the classification runs, and version_id records which threshold version produced them.
ColumnTypeKindWhat it isHow it is computed
cap_class_idsmallintcomputedThe capability answer, C1–CN.Maximum limitation: the worst class among the 17 capability elements, each rated against thr.class_range.
cap_subclasschar(1)computedThe limitation letter, e.g. s for soil physical.The subclass letter of the governing element, from ref.element.subclass_letter.
cap_governingtextcomputedWhich element produced the capability class.The worst-rated element. Ties resolve to the one with the lowest confidence.
cap_confrealcomputedPublished confidence for capability.The governing element’s own confidence, never an average. An average can never fall below its lowest member, so averaging always overstates.
cap_completenessrealcomputedPopulated fraction of the capability module.Count of elements with a value, over the count applicable to the production system.
wat_class_idsmallintcomputedThe water answer, W0–W4.Maximum limitation over the 15 water parameters of the selected source. W0 means no record held — it is not a rating.
wat_subclasschar(1)computedThe water limitation letter.As capability.
wat_governingtextcomputedWhich parameter produced the water class.As capability.
wat_confrealcomputedPublished confidence for water.As capability.
wat_completenessrealcomputedPopulated fraction of the water module.As capability.
leg_class_idsmallintcomputedThe land rights answer, E0–E3.Any intersection, not majority by area. The most restrictive designation wins. E0 where no register is held — never promoted.
leg_causetextcomputedWhich of the six checks produced it.The most restrictive intersecting designation.
any_fragilebooleancomputedCould a small measurement error change a class?TRUE where any element sits within 1σ of a class boundary. σ is the published RMSE of the source.
exclusion_classtextcomputedWhy this hectare is out of scope, if it is.From land cover: water, artificial surface or consolidated rock. Excluded cells are skipped by later jobs.

Computed on read — 295, never stored

Five values for each of the 59 scorable elements. All are a deterministic function of the 50 inputs and thr.class_range. The detail panel reads one cell: 33 values against 85 threshold rows, sub-millisecond. Storing them would cost ~500 GB, turn a threshold change into a rewrite of 215 M rows, and force one threshold version per row.
ValuePerCountWhat it isHow it is computed, on the fly
_classelement59The class this element falls into for this hectare.SELECT class_id FROM thr.class_range WHERE element_code=$1 AND version_id=$2 AND value >= value_lo AND value < value_hi. An 85-row table, permanently in memory.
_rankelement59How limiting that class is, on the ordinal scale.Joined from ref.class.rank. Feeds the MAX(rank) that produces the module answer.
_governingelement59Is this the element that decided the module class?TRUE where rank equals the module maximum. Ties resolve to the lowest confidence.
_confidenceelement59How much to trust this element on this hectare.CBRT( SQRT(method × resolution) × boundary × threshold ). Method and resolution are constant per source; boundary is one subtraction.
_fragileelement59Would a small measurement error change the class?TRUE where the distance to the nearest class boundary is under 1σ. σ is the published RMSE of the source.
Five elements are blocked and produce none of these. LQ-SP-02 workability, LQ-SP-04 sealing, LQ-SC-03 nutrient availability, and the two suitability mirrors. The inputs exist — texture, bulk density, organic carbon are all published layers — but the function that combines them into an index has never been written down. Until it is, there is no target quantity to compute, and confidence cannot be scored either: component 1 asks how a value was acquired, and there is no acquisition path to name. They are unscorable, not scored low — which is why the ceiling table reports 59 of 64 rather than scoring all 64 with five poor figures at the bottom.

Crop suitability — computed per crop, never stored

Not part of the 365, because it is not one value per hectare — it is one per hectare per crop per production system. Storing it was 4.3 billion rows holding a comparison that is cheap to redo.
-- suitability of one crop on one hectare
SELECT cr.element_code, cr.class_id
FROM   thr.crop_requirement cr
JOIN   obs.cell c ON c.cell_id = $1
WHERE  cr.crop_id = $2 AND cr.system_id = $3 AND cr.version_id = $4
  AND  the cell’s value for cr.element_code BETWEEN cr.value_lo AND cr.value_hi
ORDER  BY cr.class_id DESC LIMIT 1;   -- maximum limitation again

The element values come from the same 33 columns. A crop class and a capability class are the same measurement rated against two different threshold sets — which is why the 16 mirrored elements share one column.

The principle, stated once. Store what was measured. Compute what was decided. Materialise only what the map cannot afford to compute.
What this trace is, and what it is not

One element followed from source raster to published hectare, naming the table and column at every hop. Its purpose is to show that the 39 tables form a single path, and that any published figure can be walked backwards to the measurement that produced it.

The values below are illustrative. No database exists and no cell has been processed. The arithmetic is real — every score shown is the stated formula evaluated on the stated inputs — but the observed value of 42.0 cm is a chosen example, not a reading.

The worked case
ElementLQ-SP-03 — Rooting conditions. Capability module, Soil Physical group, subclass letter s.
CellOne 1 ha cell in Makkah province. 10,000 m².
Threshold versionv1.0-alues · status under_review · maturity source_validated (0.80).
Question being answeredCan this hectare physically support cultivation, and how far can that answer be relied on?

The path — nine hops

1
The source is registered
src.data_source
SoilGrids 250 m is entered once, with origin = 'external', licence CC-BY 4.0, native resolution 250 m, access route API. Because the origin is external the project can acquire it without ministry involvement — unlike every column in obs.land_rights.
code = SOILGRIDS_250 · origin = external
2
The source is bound to the element
src.element_source
One row joins SOILGRIDS_250 to LQ-SP-03 at priority = 1, with derivation = 'model' and the chain recorded verbatim. This row is why the element later scores 0.70 on acquisition method: a model prediction, not a direct sensor reading.
derivation_chain = 'SoilGrids bdod + bdricm → depth-to-restriction → 1 ha zonal mean'
3
The catalogue resolves where the value goes
ref.element → storage_table, storage_column
The classification routine does not hold a hard-coded mapping. It reads storage_table = 'obs.capability' and storage_column = 'rooting_depth_cm' from the catalogue and resolves the column dynamically. Adding or retiring an element is a catalogue edit, not a code change.
obs.capability.rooting_depth_cm · direction = higher_better
4
The measurement is persisted
obs.capability
The zonal mean is written to the cell’s row, in the province partition, with obs_date set to the reference date of the source and not the load date. The measured value is kept, not just the class it produced — which is what makes threshold revision a query rather than a raster reprocess.
cell_id = 20700041832 · rooting_depth_cm = 42.0 · province_id = 02
5
The value meets a class range
thr.class_range
For LQ-SP-03 under version v1.0-alues, the range containing 42.0 is C4 = 25–50 cm. Ranges cannot overlap: an EXCLUDE constraint on the range prevents two classes claiming the same value. The range is source_validated, not approved — traced to its publication but not assessed for Saudi conditions.
42.0 ∈ [25, 50) → C4 · maturity 0.80
6
The element class is recorded
classify.element_breakdown()
One row per element per cell per version — about 9.4 B rows, the largest table in the design, sub-partitioned by element. This is the audit trail: without it a class could be reported but not explained.
element_code = LQ-SP-03 · class = C4 · rank = 4 · version_id = 1
7
Confidence is computed for this element on this cell
classify.element_breakdown()
Four components. Method satellite_modelled = 0.70. Resolution: a 250 m pixel against a 107.46 m cell gives 1/(1 + 0.5·log₂(250/107.46)) = 0.68. Boundary: 42.0 is 8.0 cm from the 50 cm edge, source RMSE 6 cm, so Φ(8/6) = Φ(1.33) = 0.91. Threshold maturity = 0.80.
source_conf = √(0.70 × 0.68) = 0.690
confidence = ∛(0.690 × 0.91 × 0.80) = 0.79 — band medium.
confidence = 0.79 · fragile_class = FALSE (d/σ = 1.33 ≥ 1.0)
8
The governing element sets the cell class
res.hectare_result · conf.result_confidence
MAX(rank) runs across all 17 capability elements on the cell. If no element ranks worse than 4, rooting depth governs, is_governing is set on its classify.element_breakdown() row, and the cell is C4s — the subclass letter taken from the governing element, not from the set of all limitations. The published confidence is 0.79, the governing element’s own figure, never an average across the 19. Water and land rights are answered separately on the same row and are not combined with it.
cap_class = C4 · composite_code = C4s · cap_confidence = 0.79
9
Cells dissolve into zones, zones into the ledger
geo.zone → res.zone_crop → res.area_ledger
Contiguous cells sharing identical capability, water and land-rights classes dissolve into a zone within one governorate. No crop participates in forming the boundary — geo.zone has no FK to crop.crop; crop verdicts attach afterwards through res.zone_crop. Zones then aggregate to the area ledger at governorate, province and national tier. The hectare in this trace lands in one ledger category, and can be walked back through all nine hops to a 42.0 cm reading from a 250 m model prediction.
area_ledger.tier = governorate · category = marginal

What the path guarantees

Every figure is reversible. A hectare in the ledger resolves to a zone, a zone to its cells, a cell to its governing element, that element to a class, the class to a class range and a stored measurement, and the measurement to a named source with a recorded derivation chain. No step is inferred at query time.

Revision does not require reprocessing. Because step 4 persists the measurement, a new threshold version re-runs steps 5 to 9 as a query over obs.*. Step 1 to 4 are untouched. Both versions coexist, distinguishable by version_id.

The weakest link is visible, not averaged away. The published confidence at step 8 is the figure computed at step 7 for one element. Where a cell is governed by an inferred element with no measurement anywhere in the country, the published number says so.