Elm implementing customTable data type - functional-programming

I am completely new to functional programming and I have an assignment to implement table data type. It is supposed to be represented as a triple:
("tableName",["key1","key2","key3"],["value1","value2","value3"])
All of the items are strings, the first is the name of the table followed by two lists, which are of the same length. For every key in the first list there is corresponding value in the second list. Keys can not be repeated, values can be repeated.
I should then implement multiple functions, for example:
- create new empty table
- insert (name, key, value)
Can anyone help me with how to implement this? I have tried multiple tutorials but none of them cover something like this.
Thanks!

Well you can start with the type definition -
type Table =
Table (String, List(String), List(String))
Now we could create myTable -
myTable =
Table ("foo", ["a", "b"], ["c", "d"])
To "implement" the data type means you would write the functions that act on the data type. Consider this extremely primitive toStr function -
toStr (Table (title, cols, rows)) =
title
++ "|"
++ String.concat(cols)
++ "|"
++ String.concat(rows)
toStr myTable
# foo|ab|cd
Perhaps you want toHtml -
toHtml (Table (title, cols, rows)) =
let
header =
cols
|> List.map(text >> List.singleton >> (th []))
|> (tr [])
body =
rows
|> List.map(text >> List.singleton >> (td []))
|> (tr [])
in
table []
[ thead [] [ header ]
, tbody [] [ body ]
]
Which produces -
<table>
<thead>
<tr>
<th>a</th>
<th>b</th>
</tr>
</thead>
<body>
<tr>
<td>c</td>
<td>d</td>
</tr>
</tbody>
</table>
Hopefully this shows an important limitation of the current Table type requirement: It only supports one header row and one data row. Consider this alternate type -
type Table
Table (String, List(String), List(List(String)))
If each data row is a List(String), we could accept List(List(String)) if we wanted more a list of rows. Or ...
type alias Datum =
String
type alias Row =
List(Datum)
type Table =
Table (String, List(Datum), List(Row))
Adjusting toStr and toHtml to support List(List(String)) is a good exercise for the reader.
Short of having your assignment, I don't know what else to add to your implementation. Maybe you could make a function that sorts the columns or rows? Maybe a function that filters out some rows based on a query? If you can provide more information, maybe I can help more.

Related

How to get a row object from a function that return a table object in plsql?

i'm trying to get a single row and save it into a variable in PLSQL.
I'm using APEX and all is around the APEX_DATA_PARSE.PARSE() function.
As the docs said, .PARSE() should return WWV_FLOW_T_PARSER_ROW for every row of results.
What i'm trying to do is to get only one row to be saved into a variable.
This is My code:
`
DECLARE
r_columns_headers WWV_FLOW_T_PARSER_ROW; --object
BEGIN
DBMS_OUTPUT.ENABLE;
BEGIN
<<populate_headers>>
select * into r_columns_headers
from apex_application_temp_files f,
table( apex_data_parser.parse(
p_content => f.blob_content,
p_add_headers_row => 'Y',
P_SKIP_ROWS => 1,
p_max_rows => 500,
p_store_profile_to_collection => 'FILE_PARSER_COLLECTION',
p_file_name => f.filename ) ) p
where f.name = '43300947378776117/DATALOAD_Test_data_main_v032.xlsx' and p.line_number = 2;
end populate_headers;
DBMS_OUTPUT.PUT_LINE(r_columns_headers.id);
end;
`
is just for test outside the main package that i'm writing.
The error i get is PL/SQL: ORA-00947 on row 8, on the select * into r_columns_headers section.
I don't know why i get not enough values, the fields are the same as they are the same type of object. The select return exactly one row, of a WWV_FLOW_T_PARSER_TABLE object. Not all columns are with data, someones are null, is this the problem?
I'm just at the beginning of learning plsql.
Thanks a lot
wwv_flow_t_parser_row
I'm trying to get a row into the r_columns_headers variable to access it in my program.
The "ORA-00947: not enough values" error is sometimes a bit confusing; in a PL/SQL context it can be backwards.
The problem is that you actually have too many values in your select list. You are doing:
select * into r_columns_headers
but you're joining two table expression, apex_application_temp_files as f and the unnested table as p. So the * is effectively doing:
select f.*, p.* into r_columns_headers
... and that object doesn't have fields for all the columns coming from f.
So you need to restrict it to the relevant data:
select p.* into r_columns_headers
... but that returns all of the object attributes as individual columns, not as a single object; but you can get the actual object with the value() function:
select value(p) into r_columns_headers
fiddle with a dummy object type and data as the real APEX types aren't available there.

Is it good to use LOOKUP in FOR EACH WHERE clause? - Progress 4GL

Is it good if we use lookup function in for each where clause? Will it cause performance issue? Please help to understand and provide the example how to avoid.
define variable cGroupID as character no-undo.
for each <table> no-lock where lookup(cGroupID,<table.fieldname>) <> 0:
**do something...**
end.
note - table field name can have multiple comma separated group
A lookup function cannot use an index, so yes you can introduce sub-par performance which can be avoided. See the following example using the sports database which will read all records when using lookup and will limit the set to what meets the criteria when breaking the parts out to individual query parts:
def var ii as int no-undo.
def var iread as int64 no-undo.
function reads returns int64:
find _file where _file._file-name = 'customer' no-lock.
find _tablestat where _tablestat._tablestat-id = _file._file-number no-lock.
return _tablestat._tablestat-read.
end function.
iread = reads().
for each customer
where lookup( customer.salesrep, 'dkp,sls' ) > 0
no-lock:
ii = ii + 1.
end.
message 'lookup - records:' ii 'read:' reads() - iread.
ii = 0.
iread = reads().
for each customer
where customer.salesrep = 'dkp'
or customer.salesrep = 'sls'
no-lock:
ii = ii + 1.
end.
message 'or - records:' ii 'read:' reads() - iread.
https://abldojo.services.progress.com/?shareId=6272e1223fb02369b2545bf4
Your example however seems to be performing a reverse lookup, ie the database field contains a comma separated list of values, which seems like not obeying the basic rules of database normalization.
If you want to keep the list in a single field, adding a word index on your comma separated field may help. You can then use contains.

expression is of wrong type for function

CREATE OR REPLACE FUNCTION k_w_b_salary(k IN NUMBER, b IN BOOLEAN)
RETURN EMP.ENAME%TYPE IS
names name_table;
BEGIN
IF (b = true) THEN
SELECT ENAME BULK COLLECT INTO names
FROM
(SELECT *
FROM EMP
ORDER BY SAL ASC)
WHERE ROWNUM <= k;
RETURN names;
ELSIF (b = false) THEN
SELECT ENAME BULK COLLECT INTO names
FROM
(SELECT *
FROM EMP
ORDER BY SAL DESC)
WHERE ROWNUM <= k;
RETURN names;
END IF;
END;
And I get this error:
12/9 PL/SQL: Statement ignored
12/16 PLS-00382: expression is of wrong type
20/9 PL/SQL: Statement ignored
20/16 PLS-00382: expression is of wrong type
I have this function that tries to find the best/worst paid employees. But i get the above error.
I think it's something to do with the ROWNUM but I am not sure.
I think the lines the error points out are not the lines with the error.
I had this function writen differently and the lines in the error where pointing to the ROWNUM <= k lines.
I have tried putting a fixed number there (<= 3) for example and I got the same error.
I have no idea what else to try, i can't really understand why this is not working.
It's not obvious to me why this is not working. I think it should work fine but obviously it dousen't.
The code for the table i use is :
CREATE OR REPLACE TYPE name_table IS TABLE OF VARCHAR2(10);
Any help is appreciated!
In the function declaration, you said
RETURN EMP.ENAME%TYPE
I assume the data type of column ENAME in table EMP is some sort of string (VARCHAR2(40) or similar) - right?
In the declarations section, you declare a variable names of data type name_table. You didn't show us the definition of the name_table type (that must be given outside the function, not in it); we can probably assume it is a nested table of some sort. Right? [EDIT - I take that back; you did show us your definition of name_table, at the end of your question.]
In the end, your function returns names. Which is of type name_table. But you said the function returns something else: EMP.ENAME%TYPE. In particular, you said the function returns a scalar data type, but you are returning a collection.
This will not work even if the collection has a single element. A table with a single "record" is not the same data type as the "record" itself - even if an actual table has a single "record" in it.
(And, much more so, when the table has three records in it!)
Rather: It seems that you want a table function: one that returns a table of things. If so, then declare the function that way. Perhaps you want the function to
RETURN NAME_TABLE
(at the top, in the function declaration)

Does MariaDB 10.1+ have array/collection types for variables?

Does MariaDB have anything like arrays for variables? (Not for storage into a table. Instead I was hoping to use them to hold values to be used individually in queries.)
For example:
SELECT ... WHERE x = myVAR[1];
What do you mean?
SELECT ... FROM tbl WHERE x IN (1,4,767,443)
SELECT ... FORM tbl .. -- and get any "rows"; this is like an array.
SET #variable := 123; -- not an array, but a scalar, for use thus:
SELECT ... WHERE x = #variable;

DynamoDB “OR” conditional Range query

Let's assume my table looks like:
Code |StartDate |EndDate |Additional Attributes...
ABC |11-24-2015 |11-26-2015 | ....
ABC |12-12-2015 |12-15-2015 | ....
ABC |10-05-2015 |10-10-2015 | ....
PQR |03-24-2015 |03-27-2015 | ....
PQR |05-04-2015 |05-08-2015 | ....
Provided a Code (c) and a date range (x, y), I need to be able to query items something like:
Query => (Code = c) AND ((StartDate BETWEEN x AND y) OR (EndDate BETWEEN x AND y))
I was planning to use a Primary Key as a Hash and Range Key (Code, StartDate) with an additional LSI (EndDate) and do a query on it.
I am not sure if there is a way to achieve this. I don't want to use the SCAN operation as it seems to scan the entire table which could be very costly.
Also, would like to achieve this in a single query.
One option would be to do this using QUERY and a FilterExpression. No need to define the LSI on this case. You would have to query by Hash Key with the EQ operator and then narrow the results with the Filter Expression. Here is an example with the Java SDK:
Table table = dynamoDB.getTable(tableName);
Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":x", "11-24-2015");
expressionAttributeValues.put(":y", "11-26-2015");
QuerySpec spec = new QuerySpec()
.withHashKey("Code", "CodeValueHere")
.withFilterExpression("(StartDate between :x and :y) or (EndDate between :x and :y)")
.withValueMap(expressionAttributeValues);
ItemCollection<QueryOutcome> items = table.query(spec);
Iterator<Item> iterator = items.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().toJSONPretty());
}
See Specifying Conditions with Condition Expressions for more details.
Additionally, although the previous query only uses the Hash Key , you can still group the records with the Range Key containing the dates in the following format:
StartDate#EndDate
Table Structure:
Code DateRange |StartDate |EndDate
ABC 11-24-2015#11-26-2015 |11-24-2015 |11-26-2015
ABC 12-12-2015#12-15-2015 |12-12-2015 |12-15-2015
ABC 10-05-2015#10-10-2015 |10-05-2015 |10-10-2015
PQR 03-24-2015#03-27-2015 |03-24-2015 |03-27-2015
PQR 05-04-2015#05-08-2015 |05-04-2015 |05-08-2015
This way If you happen to query only by Hash Key you would still get the records sorted by the dates. Also, I believe it is a good idea to follow the advice given about the unambiguous date format.nu

Resources