Pass multiple sets or arrays of values to a function
You can achieve that with a simple SQL function. Key feature is the function generate_subscripts()
:
CREATE OR REPLACE FUNCTION f_attendance(_arr2d int[])
RETURNS SETOF attendance AS
$func$
SELECT a.*
FROM generate_subscripts($1, 1) i
JOIN attendance a ON a.class = $1[i][1]
AND a.section = $1[i][2]
$func$ LANGUAGE ROWS 10 sql STABLE;
Call:
SELECT * FROM f_attendance(ARRAY[[1,1],[2,2]]);
Or the same with an array literal - which is more convenient in some contexts, especially with prepared statements:
SELECT * FROM f_attendance('{{1,1},{2,2}}');
The function always expects a 2D array. Even if you pass a single pair, nest it:
SELECT * FROM f_attendance('{{1,1}}');
Audit of your implementation
You made the function
VOLATILE
, but it can beSTABLE
. Per documentation:Because of this snapshotting behavior, a function containing only
SELECT
commands can safely be markedSTABLE
.Related:
- How to pass a parameter into a date function
You also use
LANGUAGE plpgsql
instead ofsql
, which makes sense if you execute the function multiple times in the same session. But then you must also make itSTABLE
or you lose that potential performance benefit. The manual once more:STABLE
andIMMUTABLE
functions use a snapshot established as of the
start of the calling query, whereas VOLATILE functions obtain a fresh
snapshot at the start of each query they execute.Your
EXPLAIN
output shows an Index Only Scan, not a sequential scan like you suspect in your comment.There is also a sort step in your
EXPLAIN
output that does not match the code you show. Are you sure you copied the rightEXPLAIN
output? How did you obtain it anyway? PL/pgSQL functions are black boxes toEXPLAIN
. Did you useauto_explain
? Details:- Postgres query plan of a UDF invocation written in pgpsql
The Postgres query planner has no idea how many array elements the passed parameter will have, so it is hard to plan the query and it may default to a sequential scan (depending on more factors). You can help by declaring the expected number of rows. If you typically don't have more than 10 items add
ROWS 10
like I did now above. And test again.
How to pass multiple arguments including arrays to a function in Bash where order is not defined and array elements can have multiple words?
How can I solve the second example, where the order or parameter can vary?
There are two universal independent of programming language solutions to join a variadic length of a list of items together that any programmers should know about:
- Pass the count...
my_func() {
local tmp optionsa title text optionsb
tmp=$1
shift
while ((tmp--)); do
optionsa+=("$1")
shift
done
title="$1"
shift
tmp=$1
shift
while ((tmp--)); do
optionsb+=("$1")
shift
done
text=$1
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func 0 "Title" 0 "Text"
my_func 0 "Title" "${#optionsb[@]}" "${optionsb[@]}" "Text"
my_func "${#optionsa[@]}" "${optionsa[@]}" "Title" "${#optionsb[@]}" "${optionsb[@]}" "Text"
- Use a sentinel value.
my_func() {
local tmp optionsa title text optionsb
while [[ -n "$1" ]]; do
optionsa+=("$1")
shift
done
title=$1
shift
while [[ -n "$1" ]]; do
optionsb+=("$1")
shift
done
text=$1
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func "" "Title" "" "Text"
my_func "" "Title" "${optionsb[@]}" "" "Text"
my_func "${optionsa[@]}" "" "Title" "${optionsb[@]}" "" "Text"
And I see two bash specific solutions:
- Pass arrays as names and use namereferences.
my_func() {
# Use unique names to avoid nameclashes
declare -n _my_func_optionsa=$1
local title=$2
declare -n _my_func_optionsb=$3
local title=$4
my_command "${_my_func_optionsa[@]}" "$title" "${_my_func_optionsb[@]}" "$text"
}
# arrays have to exists
my_func optionsa "Title" optionsb "Text"
- Parse the arguments like a real man. This is actually universal solution, as it generally performs data serialization when creating list of arguments and then data deserialization when reading the arguments - the format (arguments as options) is specific to shell.
my_func() {
local args
# I am used to linux getopt, getopts would work as well
if ! args=$(getopt -n "$my_func" -o "a:t:b:x:" -- "$@"); then
echo "my_func: Invalid arguments" >&2
return 1
fi
set -- "$args"
local optionsa title optionsb text
while (($#)); do
case "$1" in
-a) optionsa+=("$2"); shift; ;;
-t) title="$2"; shift; ;;
-b) optionsb+=("$2"); shift; ;;
-x) text="$2"; shift; ;;
*) echo "my_func: Error parsing argument: $1" >&2; return 1; ;;
esac
shift
done
my_command "${optionsa[@]}" "$title" "${optionsb[@]}" "$text"
}
my_func -a opta1 -a opta2 -t Title -b optb1 -b optb2 -x text
# or build the options list from arrays:
# ie. perform data serialization
args=()
for i in "${optionsa[@]}"; do
args+=(-a "$i")
done
args+=(-t "title")
for i in "${optionsb[@]}"; do args+=(-b "$i"); done
args+=(-x "text")
my_func "${args[@]}"
Generally if a function has constant and small count of arguments, just use the arguments. If functions get complicated with more edge cases, I recommend to parse the arguments like a man - makes the function versatile and abstract, easy to expand and implement edge cases and handle corner cases and errors, easy to understand by other programmers, easily readable and parsable by human eyes.
Because your example codes may some problems, I recommend to research how does quoting work in shelll, specifically how "${array[@]}"
differ from ${array[@]}
, research how [@]
differ from [*]
, how does and when word splitting expansion is performed and how it affects the parameters. All the unquoted array expansions in your code suffer from word splitting - the spaces will not be preserved, also in the first example.
pass multiple arrays and values into javascript function
You can use this function to get multiple selected options from select:
function get_selected_data(o){
var selectedOptions = [];
for (var i = 0; i < o.options.length; i++){
if(o.options[i].selected){
selectedOptions.push('"' + o.options[i].value + '"');
}
}
if(selectedOptions.length){
return '[]=[' + selectedOptions.join(',') + ']';
} else {
return '';
}
}
For example:
var queryString = "?fund" + get_selected_data(document.getElementById('fund'));
queryString += "&agent" + get_selected_data(document.getElementById('agent'));
queryString += "&fromDate=" + fromDate;
queryString += "&toDate=" + toDate;
c++ pass multiple data types (including arrays of different dimensions) to function
You could use constexpr-if:
#include <iostream>
#include <type_traits>
template <class D = double>
class Tensor {
public:
using content_dtype = D; // put it here for everyone to see
template <class T>
Tensor(const T& input) {
if constexpr (std::is_arithmetic_v<T>) {
if constexpr (std::is_integral_v<T>) {
if constexpr (std::is_unsigned_v<T>) {
std::cout << "arithmetic::itegral::unsigned\n";
} else {
std::cout << "arithmetic::itegral::signed\n";
}
} else {
std::cout << "arithmetic::floating_point\n";
}
} else if constexpr (std::is_array_v<T>) {
auto dim = std::extent_v<T>;
std::cout << "array with extent " << dim << '\n';
}
}
};
int main() {
unsigned a;
int b;
double c;
int d[10];
Tensor A{a};
Tensor B{b};
Tensor C{c};
Tensor D{d};
}
Output:
arithmetic::itegral::unsigned
arithmetic::itegral::signed
arithmetic::floating_point
array with extent 10
How to pass multiple function parameters in an array in php?
The values are empty, because with the foreach you are overwriting existing values.
You can even write it more simple and use array shorthand syntax with brackets for better readability.
The null coalesce operator is syntactic sugar to avoid writing isset()
and also is ternary. If it is set, it will return its contents, otherwise set to an empty array.
new_action(['actions' => ['ACTION1', 'ACTION2'], 'tables' => ['table1', 'table2']]);
function new_action($p = array()): void {
$tables = $p['tables'] ?? [];
$actions = $p['actions'] ?? [];
var_dump($tables);
var_dump($actions);
}
array(2) { [0] => string(6) "table1" [1] => string(6) "table2" }
array(2) { [0] => string(7) "ACTION1" [1] => string(7) "ACTION2" }
Related Topics
How to Avoid "Table Mutating" Errors
Athena Presto - Multiple Columns from Long to Wide
Transfer Data Between Databases with Postgresql
How to Use Explain Plan to Optimize Queries
Improving Query Speed: Simple Select in Big Postgres Table
SQL Delete Records Within a Specific Range
How to Make Shiny Reactivity Work with SQL Database
How to Add a Column to Large SQL Server Table
Fast Update of Access Data with Excel Data Using Excel Vba
Why Does Microsoft SQL Server Check Columns But Not Tables in Stored Procs
How to Find the Size of an Array in Postgresql
Transposing Rows in to Colums in SQL Server 2005
Big Query - Create a Table/View from a Temp Table
Understanding the Differences Between Cube and Rollup
SQL Query to Add a New Column After an Existing Column in SQL Server 2005
For Each Quarter Between Two Dates, Add Rows Quarter by Quarter in SQL Server