@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 12.2 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import{neverAbortedSignal as e}from"../../arcadeEnvironment.js";import{throwIfCancelled as t,FeatureSetError as r}from"../support/errorsupport.js";import{FeatureSet as s}from"../support/FeatureSet.js";import{isDate as a,isLuxonDate as i,isArcadeTime as l,isArcadeDate as o,isArcadeDateOnly as n,cloneField as u,defaultMaxRecords as h}from"../support/shared.js";import{reformulateWithoutField as c,toWhereClause as d,translateFunctionToDatabaseSpecific as f,convertColumnReferenceToSql as p,makeToday as N,makeSqlFromDateTimeParameter as g,makeTimeString as S,arcadeDateToSqlString as m,arcadeDateOnlyToSqlString as T,convertIntervalToSql as C,combine as w,scanForField as _}from"../support/sqlUtils.js";import{SqlError as v}from"../../../core/sql/errorSupport.js";import y from"../../../core/sql/WhereClause.js";class W{constructor(e){this.field=e,this.sqlRewritable=!1}postInitialization(e,t){}}class A extends W{constructor(e){super(e),this.sqlRewritable=!0}extractValue(e){return e.attributes[this.field.name]}rewriteSql(e){return{rewritten:this.sqlRewritable,where:e}}}class E extends W{constructor(e,t,r){super(u(e)),this.originalField=e,this.sqlRewritable=!0,this.field.name=t,this.field.alias=r}rewriteSql(e,t){return{rewritten:this.sqlRewritable,where:c(e,this.field.name,this.originalField.name,t.getFieldsIndex())}}extractValue(e){return e.attributes[this.originalField.name]}}class F extends W{constructor(e,t,r){super(e),this.codefield=t,this._stringToCode=r,this._codeToString={};for(const s in r)this._codeToString[r[s]]=s;this.sqlRewritable=!0}static{this.BADNESS="_!!!_BAD_LKP_!!!!"}rewriteSql(e,t){const r=this.evaluateNodeToWhereClause(e.parseTree,0,this.field.name,this.codefield instanceof y?d(this.codefield,0):this.codefield,e.parameters);return r.includes(F.BADNESS)?{rewritten:!1,where:e}:{rewritten:this.sqlRewritable,where:y.create(r,{fieldsIndex:t._parent.getFieldsIndex(),timeZone:t.dateFieldsTimeZoneDefaultUTC})}}evaluateNodeToWhereClause(e,t,r=null,s=null,u){switch(e.type){case"interval":return C(this.evaluateNodeToWhereClause(e.value,t,r,s,u),e.qualifier,e.op);case"case-expression":{let s=" CASE ";"simple"===e.format&&(s+=this.evaluateNodeToWhereClause(e.operand,t,r,F.BADNESS,u));for(const a of e.clauses)s+=" WHEN "+this.evaluateNodeToWhereClause(a.operand,t,r,F.BADNESS,u)+" THEN "+this.evaluateNodeToWhereClause(a.value,t,r,F.BADNESS,u);return null!==e.else&&(s+=" ELSE "+this.evaluateNodeToWhereClause(e.else,t,r,F.BADNESS,u)),s+=" END ",s}case"parameter":{const r=u[e.value.toLowerCase()];return"string"==typeof r?"'"+r.toString().replaceAll("'","''")+"'":a(r)||i(r)?g(r,t):l(r)?S(r,t):o(r)?m(r,t):n(r)?T(r,t):Array.isArray(r)?r.map(e=>"string"==typeof e?"'"+e.toString().replaceAll("'","''")+"'":a(e)||i(e)?g(e,t):l(e)?S(e,t):o(e)?m(e,t):n(e)?T(e,t):e.toString()):r.toString()}case"expression-list":{const a=[];for(const i of e.value)a.push(this.evaluateNodeToWhereClause(i,t,r,s,u));return a}case"unary-expression":return" ( NOT "+this.evaluateNodeToWhereClause(e.expr,t,r,F.BADNESS,u)+" ) ";case"binary-expression":switch(e.operator){case"AND":return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" AND "+this.evaluateNodeToWhereClause(e.right,t,r,s,u)+") ";case"OR":return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" OR "+this.evaluateNodeToWhereClause(e.right,t,r,s,u)+") ";case"IS":if("null"!==e.right.type)throw new v("UnsupportedIsRhs");return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" IS NULL )";case"ISNOT":if("null"!==e.right.type)throw new v("UnsupportedIsRhs");return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" IS NOT NULL )";case"IN":{if("expression-list"===e.right.type){if("column-reference"===e.left.type&&e.left.column.toUpperCase()===this.field.name.toUpperCase()){const a=[];let i=!0;for(const t of e.right.value){if("string"!==t.type){i=!1;break}if(void 0===this._stringToCode[t.value]){i=!1;break}a.push(this._stringToCode[t.value].toString())}if(i)return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" IN ("+a.join(",")+")) "}const a=this.evaluateNodeToWhereClause(e.right,t,r,s,u);return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" IN ("+a.join(",")+")) "}const a=this.evaluateNodeToWhereClause(e.right,t,r,s,u);return Array.isArray(a)?" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" IN ("+a.join(",")+")) ":" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" IN ("+a+")) "}case"NOT IN":{if("expression-list"===e.right.type){if("column-reference"===e.left.type&&e.left.column.toUpperCase()===this.field.name.toUpperCase()){const a=[];let i=!0;for(const t of e.right.value){if("string"!==t.type){i=!1;break}if(void 0===this._stringToCode[t.value]){i=!1;break}a.push(this._stringToCode[t.value].toString())}if(i)return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" NOT IN ("+a.join(",")+")) "}const a=this.evaluateNodeToWhereClause(e.right,t,r,s,u);return" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" NOT IN ("+a.join(",")+")) "}const a=this.evaluateNodeToWhereClause(e.right,t,r,s,u);return Array.isArray(a)?" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" NOT IN ("+a.join(",")+")) ":" ("+this.evaluateNodeToWhereClause(e.left,t,r,s,u)+" NOT IN ("+a+")) "}case"BETWEEN":{const s=this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u);return" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" BETWEEN "+s[0]+" AND "+s[1]+" ) "}case"NOTBETWEEN":{const s=this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u);return" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" NOT BETWEEN "+s[0]+" AND "+s[1]+" ) "}case"LIKE":return""!==e.escape?" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" LIKE "+this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u)+" ESCAPE '"+e.escape+"') ":" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" LIKE "+this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u)+") ";case"NOT LIKE":return""!==e.escape?" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" NOT LIKE "+this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u)+" ESCAPE '"+e.escape+"') ":" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" NOT LIKE "+this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u)+") ";case"<>":case"=":if("column-reference"===e.left.type&&"string"===e.right.type){if(e.left.column.toUpperCase()===this.field.name.toUpperCase()&&void 0!==this._stringToCode[e.right.value.toString()])return" ("+s+" "+e.operator+" "+this._stringToCode[e.right.value.toString()].toString()+") "}else if("column-reference"===e.right.type&&"string"===e.left.type&&e.right.column.toUpperCase()===this.field.name.toUpperCase())return" ("+this._stringToCode[e.left.value.toString()].toString()+" "+e.operator+" "+s+") ";return" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" "+e.operator+" "+this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u)+") ";case"<":case">":case">=":case"<=":case"*":case"-":case"+":case"/":case"||":return" ("+this.evaluateNodeToWhereClause(e.left,t,r,F.BADNESS,u)+" "+e.operator+" "+this.evaluateNodeToWhereClause(e.right,t,r,F.BADNESS,u)+") "}case"null":return"null";case"boolean":return!0===e.value?"1":"0";case"string":return"'"+e.value.toString().replaceAll("'","''")+"'";case"timestamp":return`timestamp '${e.value}'`;case"date":return`date '${e.value}'`;case"time":return`time '${e.value}'`;case"number":return e.value.toString();case"current-time":return N(e.mode,t);case"current-user":return"CURRENT_USER";case"column-reference":return r&&r.toLowerCase()===e.column.toLowerCase()?"("+s+")":p(e);case"data-type":return e.value;case"function":{const s=this.evaluateNodeToWhereClause(e.args,t,r,F.BADNESS,u);return f(e.name,s,t)}}throw new v("UnsupportedSyntax",{node:e.type})}extractValue(e){if(this.codefield instanceof y){const t=this.codefield.calculateValueCompiled(e);return this._codeToString[y.convertValueToStorageFormat(t)]}return this._codeToString[e.attributes[this.codefield]]}}class x extends W{constructor(e,t){super(e),this._sql=t}rewriteSql(e,t){return{rewritten:!0,where:c(e,this.field.name,d(this._sql,0),t.getFieldsIndex())}}extractValue(e){return y.convertValueToStorageFormat(this._sql.calculateValueCompiled(e),this.field.type)}}class I extends s{static findField(e,t){for(const r of e)if(r.name.toLowerCase()===t.toString().toLowerCase())return r;return null}constructor(e){super(),this.declaredClass="esri.arcade.featureset.actions.Adapted",this._maxProcessing=30,this._parent=e.parentfeatureset,this._adaptedFields=e.adaptedFields,this._extraFilter=e.extraFilter}_initialiseFeatureSet(){this.geometryType=this._parent.geometryType,this.objectIdField=this._parent.objectIdField,this.globalIdField=this._parent.globalIdField,this.spatialReference=this._parent.spatialReference,this.hasM=this._parent.hasM,this.hasZ=this._parent.hasZ,this.typeIdField=this._parent.typeIdField,this.types=this._parent.types,this.fields=[];for(const e of this._adaptedFields)e.postInitialization(this,this._parent),this.fields.push(e.field)}async _queryAll(){return await this._ensureLoaded(),this._extraFilter?(await this.query({abortSignal:e})).features:this._calculateFields(await this._parent.queryAll(e))}async query(e){let r=e.where??null;const s=this._reformulateWithoutAdaptions(r),a=s.cannot;r=s.where;let i=!1,l=e.orderBy;if(null!=l){i=!0;const e=[];for(const t of this._adaptedFields)if(!(t instanceof A)&&!0===l.scanForField(t.field.name)){if(!(t instanceof E)){l=null,i=!1;break}e.push({field:t.field.name,newfield:t.originalField.name})}l&&e.length>0&&(l=l.replaceFields(e))}null!=r?null!=this._extraFilter&&(r=w(this._extraFilter,r)):r=this._extraFilter,await this._ensureLoaded();const o=await this._parent.query({...e,where:r,orderBy:l});return t(e.abortSignal),a?{...o,filterApplied:!1,ordered:!!i&&o.ordered,features:this._calculateFields(o.features)}:{...o,ordered:!!i&&o.ordered,features:this._calculateFields(o.features)}}async*_calculateFields(e){for await(const t of e)yield t.map(e=>{const t={};for(const r of this._adaptedFields)t[r.field.name]=r.extractValue(e);return{attributes:t,geometry:e.geometry}})}async queryStat(e){let t=!1,r=e.field,s=this._reformulateWithoutAdaptions(r);t=s.cannot,r=s.where;let a=e.where??null;if(s=this._reformulateWithoutAdaptions(a),t=t||s.cannot,a=s.where,null!=a?null!==this._extraFilter&&(a=w(this._extraFilter,a)):a=this._extraFilter,t)return null==a&&null==e.spatialFilter?this._manualStat(e.stat,r,e.limit??h,e.abortSignal):{calculated:!1};const i=await this._parent.queryStat({...e,field:r,where:a});return i.calculated?i:null==a&&null==e.spatialFilter?this._manualStat(e.stat,r,e.limit??h,e.abortSignal):{calculated:!1}}async canQueryAggregate(e){for(const a of e.groupBy)for(const e of this._adaptedFields)if(a.toLowerCase()===e.field.name.toLowerCase()&&!(e instanceof A))return!1;const t=[];for(const a of e.statistics)if(null!==a.workingexpr){const e=this._reformulateWithoutAdaptions(a.workingexpr);if(e.cannot)return!1;const r=a.clone();r.workingexpr=e.where,t.push(r)}else t.push(a);let r=e.where??null;const s=this._reformulateWithoutAdaptions(r);return!s.cannot&&(r=s.where,null!==r?null!==this._extraFilter&&(r=w(this._extraFilter,r)):r=this._extraFilter,this._parent.canQueryAggregate({...e,statistics:t,where:r}))}async queryAggregate(e){const t=[];for(const i of e.statistics)if(null!==i.workingexpr){const e=this._reformulateWithoutAdaptions(i.workingexpr);if(e.cannot)throw new r("NeverReach");const s=i.clone();s.workingexpr=e.where,t.push(s)}else t.push(i);let s=e.where??null;const a=this._reformulateWithoutAdaptions(s);if(a.cannot)throw new r("NeverReach");return s=a.where,null!==s?null!==this._extraFilter&&(s=w(this._extraFilter,s)):s=this._extraFilter,this._parent.queryAggregate({...e,statistics:t,where:s})}_reformulateWithoutAdaptions(e){const t={cannot:!1,where:e};if(null!==e)for(const r of this._adaptedFields)if(!0===_(e,r.field.name)){const s=r.rewriteSql(e,this);if(!0!==s.rewritten){t.cannot=!0,t.where=null;break}t.where=s.where}return t}}export{I as AdaptedFeatureSet,W as AdaptedField,E as FieldRename,A as OriginalField,x as SqlExpressionAdapted,F as StringToCodeAdapted};