Indexed array in query - openapi

I am struggling to write a parameter annotation for a field that would have to result as indexed array of integers:
voucher_products[0]: 23
voucher_products[1]: 102
voucher_products[2]: 233
I tried the following
* #OA\Parameter(
* name="voucher_products",
* in="query",
* description="",
* required=false,
* #OA\Schema(
* type="array",
* #OA\Items(
* type="integer",
* )
* )
* ),
I complete the form this way:
form
The result I get in the query string parameters is
voucher_products: 23
voucher_products: 102
voucher_products: 233
If I check this field in $_POST its final value is voucher_products=233, since this doesn't turn to be an array.
What am I doing wrong?

OpenAPI Specification curently doesn't have a way to represent query strings containing an indexed array such as
?arr[0]=val1&arr[1]=val2&arr[2]=val3&...
Here's are the related issues in the OpenAPI Specification repository:
Are indexes in the query parameter array representable?
Support deep objects for query parameters with deepObject style
However, if your API can accept the array with just square brackets but without the indexes
?voucher_products[]=23&voucher_products[]=102&voucher_products[]=233
then you can define it as a parameter with name="voucher_products[]".

Related

Spark - Column expression

I came across the following express, I know what does it mean - department("name"). I am curious to know, what it is resolved to. please share your inputs .
department("name") - it is used to refer the column with the name "name". Hope I am correct ? But , what it is resolved to, it seems like auxiliary constructor
From https://spark.apache.org/docs/2.4.5/api/java/index.html?org/apache/spark/sql/DataFrameWriter.html,
// To create Dataset[Row] using SparkSession
val people = spark.read.parquet("...")
val department = spark.read.parquet("...")
people.filter("age > 30")
.join(department, people("deptId") === department("id"))
.groupBy(department("name"), people("gender"))
.agg(avg(people("salary")), max(people("age")))
department("name") is just syntactic sugar for calling apply function:
department.apply("name") which returns Column
from Spark API, Dataset object:
/**
* Selects column based on the column name and returns it as a [[Column]].
*
* #note The column name can also reference to a nested column like `a.b`.
*
* #group untypedrel
* #since 2.0.0
*/
def apply(colName: String): Column = col(colName)

Postgres not using index for date field

I have created index like
CREATE INDEX bill_open_date_idx ON bill USING btree(date(open_date));
and,
Column | Type
open_date | timestamp without time zone
And explain analyse are as follows
CASE 1
explain analyze select * from bill where open_date >=date('2018-01-01');
Seq Scan on bill (cost=0.00..345264.60 rows=24813 width=1132) (actual time=0.007..1305.730 rows=5908 loops=1)
Filter: (open_date >= '2018-01-01'::date)
Rows Removed by Filter: 3238812
Total runtime: 1306.176 ms
CASE 2
explain analyze select * from bill where open_date>='2018-01-01';
Seq Scan on bill (cost=0.00..345264.60 rows=24813 width=1132) (actual time=0.006..1220.697 rows=5908 loops=1)
Filter: (open_date>= '2018-01-01 00:00:00'::timestamp without time zone)
Rows Removed by Filter: 3238812
Total runtime: 1221.131 ms
CASE 3
explain analyze select * from bill where date(open_date) >='2018-01-01';
Index Scan using idx_bill_open_date on bill (cost=0.43..11063.18 rows=22747 width=1132) (actual time=0.016..4.744 rows=5908 loops=1)
Index Cond: (date(open_date) >= '2018-01-01'::date)
Total runtime: 5.236 ms
(3 rows)
I did enough research on why this is happening, but there is no proper explanations anywhere. Only case 3 is using the index I have created, but not others. Why is this happening?
As far as my understanding goes, case 2 searches for string equivalent of the column open_date and hence it is not using index. But why not case 1. Also, please correct me if I am wrong.
Thanks in advance!
Edit 1: Also, I'd be delighted to know what is happening in depth.
Following is an excerpt from the gist (https://gist.github.com/cobusc/5875282)
It is strange though that PostgreSQL rewrites the function used to
create the index to a canonical form, but does not seem to do the same
when the function is used in the WHERE clause (in order to match the
index function).
Still, I am unclear why the developers of postgres didn't think of fetching any nearby matching index (Or is my index useless until I cast explicitly to date as in case 3). Considering Postgres is highly evolved and scalable.
A b-tree index can only be used for a search condition if the condition looks like this:
<indexed expression> <operator> <expression that is constant during the index scan>
The <indexed expression> must be the expression you used in the CREATE INDEX statement.
The <operator> must belong to the default operator class for the data type and the index access method, or to the operator class specified in CREATE INDEX.
The <expression that is constant during the index scan> can be a constant or can contain IMMUTABLE or STABLE functions and operators, but nothing VOLATILE.
All your queries satisfy the last two conditions, but only the third one satisfies the first one. That is why only that query can use the index.
For documentation that covers this in excruciating detail, see the comment for match_clause_to_indexcol in postgresql/src/backend/optimizer/path/indxpath.c:
/*
* match_clause_to_indexcol()
* Determine whether a restriction clause matches a column of an index,
* and if so, build an IndexClause node describing the details.
*
* To match an index normally, an operator clause:
*
* (1) must be in the form (indexkey op const) or (const op indexkey);
* and
* (2) must contain an operator which is in the index's operator family
* for this column; and
* (3) must match the collation of the index, if collation is relevant.
*
* Our definition of "const" is exceedingly liberal: we allow anything that
* doesn't involve a volatile function or a Var of the index's relation.
* In particular, Vars belonging to other relations of the query are
* accepted here, since a clause of that form can be used in a
* parameterized indexscan. It's the responsibility of higher code levels
* to manage restriction and join clauses appropriately.
*
* Note: we do need to check for Vars of the index's relation on the
* "const" side of the clause, since clauses like (a.f1 OP (b.f2 OP a.f3))
* are not processable by a parameterized indexscan on a.f1, whereas
* something like (a.f1 OP (b.f2 OP c.f3)) is.
*
* Presently, the executor can only deal with indexquals that have the
* indexkey on the left, so we can only use clauses that have the indexkey
* on the right if we can commute the clause to put the key on the left.
* We handle that by generating an IndexClause with the correctly-commuted
* opclause as a derived indexqual.
*
* If the index has a collation, the clause must have the same collation.
* For collation-less indexes, we assume it doesn't matter; this is
* necessary for cases like "hstore ? text", wherein hstore's operators
* don't care about collation but the clause will get marked with a
* collation anyway because of the text argument. (This logic is
* embodied in the macro IndexCollMatchesExprColl.)
*
* It is also possible to match RowCompareExpr clauses to indexes (but
* currently, only btree indexes handle this).
*
* It is also possible to match ScalarArrayOpExpr clauses to indexes, when
* the clause is of the form "indexkey op ANY (arrayconst)".
*
* For boolean indexes, it is also possible to match the clause directly
* to the indexkey; or perhaps the clause is (NOT indexkey).
*
* And, last but not least, some operators and functions can be processed
* to derive (typically lossy) indexquals from a clause that isn't in
* itself indexable. If we see that any operand of an OpExpr or FuncExpr
* matches the index key, and the function has a planner support function
* attached to it, we'll invoke the support function to see if such an
* indexqual can be built.

How to search from multiple values in single field (Bus Stops in GTFS)?

In the GTFS data for Denver, the BUS_STOPS table stores multiple comma-separated values in the ROUTES column:
28, 19, 44, 10, 32
I'm selecting BUS_ROUTES that are within a distance of a school.
But to select the corresponding stops along those routes means trying to find a bus stop (ex. that serves bus 44) from the list I described above - I'm not sure how to do this.
The comment below helped me figure out selecting 1 route by its value would look like this:
select * from BUS_STOPS where ROUTES like '% 44,%';
...which returns records that contain 44 in one of the listed values.
So how would I replace the static value of 44 to be the value of the ROUTES field in the BUS_ROUTES table?
The BUS_ROUTES table looks like this:
...and the BUS_STOPS table looks like this:
I'm using PostgreSQL to query the GTFS data.
Convert the string to an array, then use an array comparison:
select *
from BUS_STOPS
where '44' = any(string_to_array(routes,',')
This can also be used as a join condition:
select *
from BUS_STOPS s
join bus_routes r on string_to_array(s.routes,',') #> string_to_array(r.routes,',')
The #> is the "contains" operator and tests if the left array (bus_stops.routes) contains all elements from right array (bus_routes.routes). Another option would be to the use overlaps operator && - it's not clear to me what exactly you want

typo3 extension: issue with function fullQuoteArray()

I am reading an extension file, and see below codes:
$GLOBALS['TYPO3_DB']->exec_UPDATEquery(
'tx_jcjob_job',
'uid = '.$this->piVars['job'],
array('hit_counter' => 'hit_counter + 1'),
array('hit_counter')
);
Then in file: class.t3lib_db.php,I checked two functions function exec_UPDATEqueryfile():
* #param string Database tablename
* #param string WHERE clause, eg. "uid=1". NOTICE: You must escape values in this argument with $this->fullQuoteStr() yourself!
* #param array Field values as key=>value pairs. Values will be escaped internally. Typically you would fill an array like "$updateFields" with 'fieldname'=>'value' and pass it to this function as argument.
* #param string/array See fullQuoteArray()
* #return pointer MySQL result pointer / DBAL object
*/
function exec_UPDATEquery($table, $where, $fields_values, $no_quote_fields = FALSE)
and function fullQuoteArray():
/**
* Will fullquote all values in the one-dimensional array so they are ready to "implode" for an sql query.
*
* #param array Array with values (either associative or non-associative array)
* #param string Table name for which to quote
* #param string/array List/array of keys NOT to quote (eg. SQL functions) - ONLY for associative arrays
* #return array The input array with the values quoted
* #see cleanIntArray()
*/
function fullQuoteArray($arr, $table, $noQuote = FALSE)
But I still got question:
how does this work: array('hit_counter')? or in other words, how does function fullQuoteArray() work? what does this mean: fullquote all values in the one-dimensional array?
On each array value the function real_escape_string (since 6.x) or mysql_real_escape (before 6.x) is used. So, every value should be SQL-Injection save.
There is no magic inside :)

Select from any of multiple values from a Postgres field

I've got a table that resembles the following:
WORD WEIGHT WORDTYPE
a 0.3 common
the 0.3 common
gray 1.2 colors
steeple 2 object
I need to pull the weights for several different words out of the database at once. I could do:
SELECT * FROM word_weight WHERE WORD = 'a' OR WORD = 'steeple' OR WORD='the';
but it feels ugly and the code to generate the query is obnoxious. I'm hoping that there's a way I can do something like (pseudocode):
SELECT * FROM word_weight WHERE WORD = 'a','the';
You are describing the functionality of the in clause.
select * from word_weight where word in ('a', 'steeple', 'the');
If you want to pass the whole list in a single parameter, use array datatype:
SELECT *
FROM word_weight
WHERE word = ANY('{a,steeple,the}'); -- or ANY('{a,steeple,the}'::TEXT[]) to make explicit array conversion
If you are not sure about the value and even not sure whether the field will be an empty string or even null then,
.where("column_1 ILIKE ANY(ARRAY['','%abc%','%xyz%']) OR column_1 IS NULL")
Above query will cover all possibility.