How to declare strings in enum - graphql

With graphql, enum can make a predefined list of elements but strings don't work.
For example:
enum Dias {
lunes
martes
miércoles
jueves
viernes
sábado
domingo
}
This returns an error GraphQLError: Syntax Error: Cannot parse the unexpected character "\u00E9".
how is it possible to make a predefined list of strings?
Edit: to give more context, I want to reflect the database schema, which is like this (with mongoose):
dias: {
type: String,
enum: ['lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo'],
lowercase: true,
required: true
}

Your syntax is correct, the only issue is that the "é" and "á" characters are not supported. The specification outlines rules for naming operations, fields, etc. The supported pattern is:
/[_A-Za-z][_0-9A-Za-z]*/
Furthermore:
Names in GraphQL are limited to this ASCII subset of possible characters to support interoperation with as many other systems as possible.
So, unfortunately, you will have to convert those accented characters to valid ones in order for your schema to be considered valid.
EDIT: You could create a custom scalar. Here's a function that takes a name, description and an array and returns a custom scalar:
const makeCustomEnumScalar = (name, description, validValues) => {
const checkValue = (value) => {
const coerced = String(value)
if (!validValues.includes(coerced)) {
throw new TypeError(`${coerced} is not a valid value for scalar ${name}`)
}
return coerced
}
return new GraphQLScalarType({
name,
description,
serialize: checkValue,
parseValue: checkValue,
parseLiteral: (ast) => checkValue(ast.value),
})
}
Now you can do something like:
const DayOfWeek = makeCustomEnumScalar('Day of Week', 'day of week enum', [
'lunes',
'martes',
'miércoles',
'jueves',
'viernes',
'sábado',
'domingo'
])
Add it to your resolvers:
const resolvers = {
DayOfWeek,
// Query, Mutation, etc.
}
And your type definitions:
scalar DayOfWeek
And then you can use it like any other scalar. If an invalid value is provided as an input or output by a query, then GraphQL will throw an error like with an enum. The only caveat is that if you're entering the values directly into your query (as opposed to using variables), you'll still need to wrap them in double quotes.

Related

How to properly escape parameters for JSONB deep query in node-postgres

When bypassing an ORM and doing direct queries to node-postgres, there are a nice pile of weird edge issues to keep in mind. For example, you have probably already encountered the fact that camelCaseColumns have to be in double-quotes, and also parameterized type casting…
client.query(`SELECT id, "authorFirstName", "authorLastName" FROM books WHERE isbn = $1::int`, [1444723448]`)
client.query(`SELECT id FROM books WHERE "authorLastName" = $1::string`, ['King']`)
JSON and JSONB types add another aspect of weirdness. The important thing to keep in mind is, "$1" is not merely a variable placeholder; it is an indicator of a discrete unit of information.
Given a table where characters is a column of type JSONB, this will not work…
client.query(
`SELECT id FROM books WHERE characters #> ([ {'name': $1::string} ])`,
['Roland Deschain']
)
This fails because the unit of information is the JSON object, not a string you're inserting into a blob of text.
This is a little more clear when one looks at a simpler SELECT and an UPDATE…
const userData = await client.query(
`SELECT characters FROM books WHERE id = $1::uuid`,
[ some_book_id ]
)
const newCharacters = JSON.stringify([
...userData[0].characters,
{ name: 'Jake' },
{ name: 'Eddie' },
{ name: 'Odetta' }
])
await this.databaseService.executeQuery(
`UPDATE books SET characters = $1::jsonb WHERE id = $2::uuid`,
[ newCharacters, some_book_id ]
)
The deep search query should be formed thusly:
const searchBundle = JSON.stringify([
{'name': 'Roland Deschain'}
])
client.query(
`SELECT id FROM books WHERE characters #> ($1::jsonb)`,
[searchBundle]
)

Create case sensitive LINQ Expression with Contains method (Case insensitive collation database)

I have a database created with a SQL_Latin1_General_CP1_CI_AS collation (which is case insensitive).
I'm creating LINQ Expressions and trying to make "Contains" method which should compare strings in a case sensitive way.
I know that I can force collation if I use something like:
CHARINDEX(N'foo' COLLATE SQL_Latin1_General_CP1_CS_AS, 'something Foo') > 0
but since I'm building expressions using LINQ to create a query, my code looks like:
using System.Linq.Expressions;
private Expression Contains(Type type, string value, Expression propertyExpression)
{
var searchValue = Expression.Constant(value, typeof(string));
var method = propertyExpression.Type.GetMethod("Contains", new[] { type });
var result = Expression.Call(propertyExpression, method, searchValue);
...
}
So, if I'm trying to use this Contains method for word 'foo', rows with 'Foo' will also be returned (which I don't want).
Is there a way that I can expand this Expression so that I can specify Case Sensitive comparison?

Inconsistent Alphanumeric Sorting with ag-grid and String Cells [duplicate]

This question already has answers here:
How to make sorting key insensitive in ag-grid?
(3 answers)
Closed 3 years ago.
Im using ag-grid-react to display a table of data from an endpoint. I have a column which contains alphanumeric values which needs to be sortable using a "natural" sort algorithm (i.e. numbers are grouped together, alphanumeric strings are grouped together...)
Below is my column definition. Sorting is enabled on the grid, and when I click the column to sort the grid, everything appears sorted except for some strings which start with a numeral that interrupt the sequence of strings beginning with C.
This happens with ag-grid's default sorting algorithm, regardless of whether or not accentedSort is true or false, and even with a basic custom sort comparator (see below.)
Column Definition:
field: 'cqttUnitPayItemDescriptionId',
headerName: 'Description',
type: 'dropdown',
editable: true,
resizable: true,
valueGetter: (p) => {
const value = p.data[p.colDef.field];
const cellDescription = p.data.description;
// returns a string value for display
// `items` is an ImmutableJs Map of objects, grouped by index, containing a `description` string property.
return value >= 0 ? items.getIn([value, 'description']) || cellDescription : value;
},
cellEditorFramework: AgGridCellEditor({ component: AgDropdownEditor, renderProps: innerProps => ({ createable: true, labelProperty: 'description', options: itemsByUnitPayItemId.getIn([innerProps.data.unitPayItemId], Map()).toList(), ...innerProps }) }),
sortable: true,
width: 250,
comparator: StringComparator
},
Custom Sort Comparator:
export function StringComparator(valueA: string = '', valueB: string = '') {
const valueALower = valueA.toLowerCase();
const valueBLower = valueB.toLowerCase();
return valueALower.localeCompare(valueBLower, 'en', { numeric: true });
}
Visual Example of the Sorting Inconsistencies:
Given the screenshot above: Manual testing of the comparator shows that the string "4' x 8' x 16' (Dragline Mat)" should come before "Construction Crew "Move Around" - Tie-Ins" (i.e. the return value of calling the comparator with those arguments respectively is -1) but clearly the grid thinks otherwise. Could it be I'm missing something regarding the scope of calls to the comparator function?
Turns out some of the strings that were being sorted contained a space at the very beginning of the strings, causing them to (properly) be sorted before numerals and alphabetical characters altogether. I've solved this issue by simply appending .trim() to the end of each value being compared in the StringComparator:
export function StringComparator(valueA: string = '', valueB: string = '') {
const valueALower = valueA.toLowerCase().trim();
const valueBLower = valueB.toLowerCase().trim();
return valueALower.localeCompare(valueBLower, 'en', { numeric: true });
}

Enum for number in GraphQL (js)

I want to allow one of the fields to be either 1, 2 or 3. I am not exactly sure how to do that in http://graphql.org/graphql-js/type/
Because I would need to do something like:
var AgeType = new GraphQLEnumType({
name: 'Age',
values: {
1: { value: 0 },
2: { value: 1 },
3: { value: 2 }
}
});
And this doesn't work because the key is a number...
It's not possible as described here: https://github.com/graphql/graphiql/issues/586
GraphQL require enum values to match [_A-Za-z][_0-9A-Za-z] RegExp
Enum variables have to start with a letter, so you will have to use String or Int type. In order to ensure that only 1,2 and 3 are passed, you may implement some kind of validation rules in the resolvers.

CKQuery with NSPredicate fails when using "CONTAINS" operator

According to Apples Class Reference CKQuery, the operator CONTAINS is one of the supported operators. However, that doesn't seem to work. I have a RecordType called myRecord, and a record with field name name type String. I try to fetch the record with two different predicates, one with "==" operator, and one with CONTAINS operator.
func getRecords() {
let name = "John"
let Predicate1 = NSPredicate(format: "name == %#",name)
let Predicate2 = NSPredicate(format: "name CONTAINS %#",name)
let sort = NSSortDescriptor(key: "Date", ascending: false)
let query = CKQuery(recordType: "myRecord", predicate: Predicate1)
// let query = CKQuery(recordType: "myRecord", predicate: Predicate2)
query.sortDescriptors = [sort]
let operation = CKQueryOperation(query: query)
operation.desiredKeys = ["name", "Date"]
operation.recordFetchedBlock = { (record) in
print(record["name"])
operation.queryCompletionBlock = { [unowned self] (cursor, error) in
dispatch_async(dispatch_get_main_queue()) {
if error == nil {
print ("sucess")
} else {
print("couldn't fetch record error:\(error?.localizedDescription)")
}
}
}
CKContainer.defaultContainer().publicCloudDatabase.addOperation(operation)
}
Using Predicate1, output is:
Optional(John)
sucess
Using Predicate2, output is:
couldn't fetch record error:Optional("Field \'name\' has a value type of STRING and cannot be queried using filter type LIST_CONTAINS")
Also using [c] to ignore casings gives a server issue.
How do I use the operator CONTAINS correctly?
EDIT:
I have now looked closer at the documentation, and seen that CONTAINS can only be used with SELF. Meaning that all String fields will be used for searching. Isn't there a better way?
It's an exception mentioned as below:
With one exception, the CONTAINS operator can be used only to test
list membership. The exception is when you use it to perform full-text
searches in conjunction with the self key path. The self key path
causes the server to look in searchable string-based fields for the
specified token string. For example, a predicate string of #"self
contains 'blue'" searches for the word “blue” in all fields marked for
inclusion in full-text searches. You cannot use the self key path to
search in fields whose type is not a string.
So, you can use 'self' instead of '%K' in order to search sub-text of string field.
For the full document written by Apple

Resources