Skip to content

Commit

Permalink
Add datetime support for querying (#154)
Browse files Browse the repository at this point in the history
* support datetime for querying

* release prep

* help updates
  • Loading branch information
gdbarron authored Sep 21, 2021
1 parent ef50d3b commit 0c9d6c8
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 32 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 3.1.0
- Add DateTime support to querying, [#68](https://github.com/Snow-Shell/servicenow-powershell/issues/68)
- Add `-between` operator
- Enhanced value validation for all operators in `New-ServiceNowQuery` which is used by `Get-ServiceNowRecord`

## 3.0.2
- Fix [#152](https://github.com/Snow-Shell/servicenow-powershell/issues/152), object conversion to json failing.

Expand Down
6 changes: 4 additions & 2 deletions ServiceNow/Public/Get-ServiceNowRecord.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@
Each array should be of the format @(field, comparison operator, value) separated by a join, either 'and', 'or', or 'group'.
For a complete list of comparison operators, see $script:ServiceNowOperator and use Name in your filter.
See the examples.
Also, see https://docs.servicenow.com/bundle/quebec-platform-user-interface/page/use/common-ui-elements/reference/r_OpAvailableFiltersQueries.html
for how to represent date values with javascript.
.PARAMETER Sort
Array or multidimensional array of fields to sort on.
Expand Down Expand Up @@ -87,6 +85,10 @@
Get incident records where state is New and short description contains the word powershell or state is In Progress.
The first 2 filters are combined and then or'd against the last.
.EXAMPLE
Get-ServiceNowRecord -Table 'Incident' -Filter @('opened_at', '-between', (Get-Date).AddMonths(-24), (get-date).AddMonths(-12)) -IncludeTotalCount
Get all incident records that were opened between 1 and 2 years ago
.EXAMPLE
Get-ServiceNowRecord -Table incident -Filter @('state', '-eq', '1') -Sort @('opened_at', 'desc'), @('state')
Get incident records where state equals New and first sort by the field opened_at descending and then sort by the field state ascending
Expand Down
49 changes: 38 additions & 11 deletions ServiceNow/Public/New-ServiceNowQuery.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -145,31 +145,58 @@ function New-ServiceNowQuery {
if ( $i -eq $filterList.Count - 1) {
throw '$Filter cannot end with a join'
}

break
}

2 {
# should be a non-value operator, eg. ='' / ISEMPTY
{ $_ -ne 1 } {
# perform data validation on all filters other than a join operator
$thisOperator = $script:ServiceNowOperator | Where-Object { $_.Name -eq $thisFilter[1] }
if ( -not $thisOperator ) {
throw ('Operator ''{0}'' is not valid' -f $thisFilter[1])
}
if ( $thisOperator.RequiresValue ) {
throw ('Value not provided, {0} {1} ?' -f $thisFilter[0], $thisOperator.QueryOperator)
if ( $thisOperator.NumValues -ne $thisFilter.Count - 2 ) {
throw ('Operator ''{0}'' requires 1 field name and {1} value(s)' -f $thisFilter[1], $thisOperator.NumValues)
}
}

2 {
# should be a non-value operator, eg. ='' / ISEMPTY
'{0}{1}' -f $thisFilter[0], $thisOperator.QueryOperator
break
}

3 {
# should be field operator value
$thisOperator = $script:ServiceNowOperator | Where-Object { $_.Name -eq $thisFilter[1] }
if ( -not $thisOperator ) {
throw ('Operator ''{0}'' is not valid', $thisFilter[1])
# should be format - field operator value

if ( $thisFilter[2] -is [DateTime] ) {
$dateGen = "'{0}','{1}'" -f $thisFilter[2].ToString('yyyy-MM-dd'), $thisFilter[2].ToString('HH:mm:ss')
'{0}{1}javascript:gs.dateGenerate({2})' -f $thisFilter[0], $thisOperator.QueryOperator, $dateGen
}
else {
'{0}{1}{2}' -f $thisFilter[0], $thisOperator.QueryOperator, $thisFilter[2]
}
'{0}{1}{2}' -f $thisFilter[0], $thisOperator.QueryOperator, $thisFilter[2]

break
}

4 {
# should be format - field operator value1 value2, where applicable, eg. between

if ( $thisFilter[2] -is [DateTime] ) {
$dateGen1 = "'{0}','{1}'" -f $thisFilter[2].ToString('yyyy-MM-dd'), $thisFilter[2].ToString('HH:mm:ss')
$dateGen2 = "'{0}','{1}'" -f $thisFilter[3].ToString('yyyy-MM-dd'), $thisFilter[3].ToString('HH:mm:ss')
'{0}{1}javascript:gs.dateGenerate({2})@javascript:gs.dateGenerate({3})' -f $thisFilter[0], $thisOperator.QueryOperator, $dateGen1, $dateGen2
}
else {
'{0}{1}{2}@{3}' -f $thisFilter[0], $thisOperator.QueryOperator, $thisFilter[2], $thisFilter[3]
}

break
}

Default {
throw ('Too many items for {0}, see the help' -f $thisFilter[0])
throw ('Too many filter items for {0}, see the help' -f $thisFilter[0])
}
}
}
Expand Down Expand Up @@ -234,7 +261,7 @@ function New-ServiceNowQuery {
}
}

$query -join ''
($query -join '').Trim('^')

}
else {
Expand Down
2 changes: 1 addition & 1 deletion ServiceNow/ServiceNow.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
RootModule = 'ServiceNow.psm1'

# Version number of this module.
ModuleVersion = '3.0.2'
ModuleVersion = '3.1.0'

# ID used to uniquely identify this module
GUID = 'b90d67da-f8d0-4406-ad74-89d169cd0633'
Expand Down
42 changes: 24 additions & 18 deletions ServiceNow/config/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,109 +68,115 @@
"Name": "-eq",
"QueryOperator": "=",
"Description": "is equal to",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-ne",
"QueryOperator": "!=",
"Description": "is not equal to",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "=''",
"QueryOperator": "ISEMPTY",
"Description": "field has no value",
"RequiresValue": false
"NumValues": 0
},
{
"Name": "=\"\"",
"QueryOperator": "ISEMPTY",
"Description": "field has no value",
"RequiresValue": false
"NumValues": 0
},
{
"Name": "!=''",
"QueryOperator": "ISNOTEMPTY",
"Description": "field has any value",
"RequiresValue": false
"NumValues": 0
},
{
"Name": "!=\"\"",
"QueryOperator": "ISNOTEMPTY",
"Description": "field has any value",
"RequiresValue": false
"NumValues": 0
},
{
"Name": "-like",
"QueryOperator": "LIKE",
"Description": "value is found anywhere in field",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-notlike",
"QueryOperator": "NOT LIKE",
"Description": "value is not found anywhere in field",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-in",
"QueryOperator": "IN",
"Description": "field is populated by one of the values",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-notin",
"QueryOperator": "NOT IN",
"Description": "field is populated by any value except for these",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-lt",
"QueryOperator": "<",
"Description": "field is less than the value. can be used with dates to represent prior to the value.",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-le",
"QueryOperator": "<=",
"Description": "field is less than or equal to the value. can be used with dates to represent prior to or the day of the value.",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-gt",
"QueryOperator": ">",
"Description": "field is greater than the value. can be used with dates to represent after the value.",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-ge",
"QueryOperator": ">=",
"Description": "field is greater than or equal to the value. can be used with dates to represent after or the day of the value.",
"RequiresValue": true
"NumValues": 1
},
{
"Name": ".startswith",
"QueryOperator": "STARTSWITH",
"Description": "field starts with the value",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-startswith",
"QueryOperator": "STARTSWITH",
"Description": "field starts with the value",
"RequiresValue": true
"NumValues": 1
},
{
"Name": ".endswith",
"QueryOperator": "%",
"Description": "field ends with the value",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-endswith",
"QueryOperator": "%",
"Description": "field ends with the value",
"RequiresValue": true
"NumValues": 1
},
{
"Name": "-between",
"QueryOperator": "BETWEEN",
"Description": "value is between 2 dates or integers",
"NumValues": 2
}
]
}

0 comments on commit 0c9d6c8

Please sign in to comment.