问:
How to get result set from PostgreSQL stored procedure?
I created a stored procedure in PostgreSQL 11 to perform CRUD operation, and it works fine for 1. Create 2. Update 3. Delete, but while I run read command by passing Condition = 4 to select a result set, I get below error.

I have used PostgreSQL function to get result set it works for me, but I need to get result using the PostgreSQL stored procedure.

Here is my code for stored procedure:

```<code>CREATE OR REPLACE PROCEDURE public.testSpCrud(
    fnam text,
    lnam text,
    id integer,
    condition integer)
LANGUAGE 'plpgsql'

AS $BODY$
declare
    countOfDisc int;
BEGIN
if condition=1 then

INSERT INTO public.employee(
    employeeid, lname, fname, securitylevel, employeepassword, hphonearea, hphone, cphonearea, cphone, street, city, state, zipcode, extzip, name, email, groomerid, type, commission, inactive, carrierid, notoallemployees, languageid, isdogwalker, ispetsitter, ismobilegroomer, ssma_timestamp)
    VALUES (4,  'Test', 'Test', 2, 2, 32, 32, 32, 32, 32, 32,32, 32, 32, 22, 22, 2, 2, 2, false, 223,true, 223, true, true, true, '2019-08-27');
end if;
 if condition =2 then
    delete from Employee where employeeid=id;
    end if;
     if condition =3 then
    update Employee set fname='Test' where employeeid=id;
    end if;
     if condition =4 then
         Select * from Employee;
    end if;
    END;
$BODY$;
</code>```

```<code>ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function testspcrud(text,text,integer,integer) line 22 at SQL statement
SQL state: 42601
</code>```

答:
Most people will suggest that when migrating MS SQL Server stored procedures to PostgreSQL, if the procedure returns a set of data (rows and columns), you change the stored procedure into a function, since functions, by nature, return sets of data.  However, as of Postgres 11, you can return result sets from a PostgreSQL Procedure using cursors, though it can be tedious to iterate over the results.

The following demonstrates how to return a set of data from a PostgreSQL procedure using an INOUT cursor:

CREATE OR REPLACE PROCEDURE test_get_data_single(
    _itemID int,
    INOUT _message text = '',
    INOUT _result_one refcursor = 'rs_resultone',
    INOUT _returnCode text = '')
LANGUAGE plpgsql
AS
$$
BEGIN
    _message := 'Test message for item ' || COALESCE(_itemID, 0);
    _returnCode := '';

  open _result_one for
    SELECT *
    FROM (values (1,2,3, 'fruit', current_timestamp - INTERVAL '5 seconds'),
                 (4,5,6, 'veggie', current_timestamp)) as t(a,b,c,d,e);

END;
$$;
```

<p>To use, call the procedure within a transaction</p>

<pre class="lang-sql prettyprint-override"><code>BEGIN;
    CALL test_get_data_single(1);
    FETCH ALL FROM "rs_resultone";
COMMIT;
</code>```

PostgreSQL also supports using Begin / End:

```<code>BEGIN;
    CALL test_get_data_single(2);
    FETCH ALL FROM "rs_resultone";
END;
</code>```

Example results from DBeaver

```<code>+--------------------------+--------------+-------------+
|    _message              | _result_one  | _returncode |
+--------------------------+--------------+-------------+
| Test message for item 2  | rs_resultone |             |
+--------------------------+--------------+-------------+
</code>```

```<code>+---+---+---+--------+---------------------|
| a | b | c | d      | e                   |
+---+---+---+--------+---------------------|
| 1 | 2 | 3 | fruit  | 2020-02-15 10:12:09 |
| 4 | 5 | 6 | veggie | 2020-02-15 10:12:09 |
+---+---+---+--------+---------------------|
</code>```

For more advanced handling of the results, use an anonymous code block to iterate over the results

DO
$$
DECLARE
    _message text = '';
    _returnCode text = '';
    _result_one refcursor;
    _result_single refcursor;
    _currentRow record;
    _i int;
BEGIN

    CALL test_get_data_single(1, _message => _message, _result_one => _result_single, _returnCode => _returnCode);

    RAISE info 'Cursor _result_single from test_get_data_single: %', _result_single;

    _i := 0;
    WHILE TRUE
    Loop
        FETCH NEXT FROM _result_single INTO _currentRow;

        IF _currentRow IS NULL Then
            EXIT;
        END IF;

        _i := _i + 1;
        RAISE info '%, array: %', _i, _currentRow;
        RAISE info '%, values: %  %  %  %', _i, _currentRow.a, _currentRow.b, _currentRow.c, _currentRow.d;
    END LOOP;

End
$$;
```

<p>Example results from DBeaver (look in the Server Output, opened with Ctrl+Shift+O):</p>

```Cursor _result_single from test_get_data_single: <unnamed portal 261>
1, array: (1,2,3,fruit,"2020-02-14 17:19:29.612822-08")
1, values: 1  2  3  fruit
2, array: (4,5,6,veggie,"2020-02-14 17:19:34.612822-08")
2, values: 4  5  6  veggie
```

<p>Example results from psql:</p>

```INFO:  Cursor _result_single from test_get_data_single: <unnamed portal 4>
INFO:  1, array: (1,2,3,fruit,"2020-02-14 17:22:50.81671-08")
INFO:  1, values: 1  2  3  fruit
INFO:  2, array: (4,5,6,veggie,"2020-02-14 17:22:55.81671-08")
INFO:  2, values: 4  5  6  veggie
```

<p>A procedure can also return two result sets, using separate <code>refcursor</code> arguments:</p>

<pre class="lang-sql prettyprint-override"><code>CREATE OR REPLACE PROCEDURE test_get_data(
    _itemID int,
    INOUT _message TEXT = '',
    INOUT _result_one refcursor = 'rs_resultone',
    INOUT _result_two refcursor = 'rs_resulttwo',
    INOUT _returnCode TEXT = '')
LANGUAGE plpgsql
AS
$$
BEGIN
    _message := 'Test message for item ' || COALESCE(_itemID, 0);
    _returnCode := '';

  open _result_one for
    SELECT *
    FROM (values (1,2,3, 'fruit', current_timestamp - INTERVAL '5 seconds'), (4,5,6, 'veggie', current_timestamp)) as t(a,b,c,d,e);

  open _result_two for
    SELECT *
    FROM (values ('one'), ('two'), ('three'), ('four')) as p(name);

END;
$$;
</code>```

Retrieve results with:

BEGIN;
    CALL test_get_data(1);
    FETCH ALL FROM "rs_resultone";
    FETCH ALL FROM "rs_resulttwo";
END;
```

<p>Or use an expanded anonymous code block for viewing the results</p>

```DO
$$
DECLARE
    _message text = '';
    _returnCode text = '';
    _result_one refcursor;
    _result_two refcursor;
    _result_single refcursor;
    _currentRow record;
    _i int;
BEGIN

    CALL test_get_data(1, _message => _message, _result_one => _result_one, _result_two => _result_two, _returnCode => _returnCode);

    RAISE info '%', _message;

    RAISE info '';
    RAISE info 'Cursor _result_one: %', _result_one;

    _i := 0;
    WHILE TRUE
    Loop
        FETCH NEXT FROM _result_one INTO _currentRow;

        IF _currentRow IS NULL Then
            EXIT;
        END IF;

        _i := _i + 1;
        RAISE info '%, array: %', _i, _currentRow;
        RAISE info '%, values: %  %  %  %', _i, _currentRow.a, _currentRow.b, _currentRow.c, _currentRow.d;

    END LOOP;

    RAISE info '';
    RAISE info 'Cursor _result_two: %', _result_two;

    _i := 0;
    WHILE TRUE
    Loop
        FETCH NEXT FROM _result_two INTO _currentRow;

        IF _currentRow IS NULL Then
            EXIT;
        END IF;

        _i := _i + 1;
       RAISE info '%: %', _i, _currentRow;

    END LOOP;
End
$$;
```

<p>Output:</p>

```Test message for item 1

Cursor _result_one: <unnamed portal 263>
1, array: (1,2,3,fruit,"2020-02-14 17:25:06.528551-08")
1, values: 1  2  3  fruit
2, array: (4,5,6,veggie,"2020-02-14 17:25:11.528551-08")
2, values: 4  5  6  veggie

Cursor _result_two: <unnamed portal 264>
1: (one)
2: (two)
3: (three)
4: (four)
```

<p>The alternative design pattern, especially for procedures that normally add/update data, but for where you occasionally want to preview results is to use <code>RAISE INFO</code> statements.  For example:</p>

<pre class="lang-sql prettyprint-override"><code>
    If _infoOnly <> 0 Then

        _infoHead := format('%-22s %-15s %-20s %-25s %-25s',
                            'State Change Preview',
                            'Parameter Name',
                            'Manager Name',
                            'Manager Type',
                            'Enabled (control_from_website=1)'
                        );

        RAISE INFO '%', _infoHead;

        FOR _previewData IN
            SELECT PV.value || ' --> ' || _newValue AS State_Change_Preview,
                   PT.param_name AS Parameter_Name,
                   M.mgr_name AS manager_name,
                   MT.mgr_type_name AS Manager_Type,
                   M.control_from_website
            FROM mc.t_param_value PV
                 INNER JOIN mc.t_param_type PT
                   ON PV.type_id = PT.param_id
                 INNER JOIN mc.t_mgrs M
                   ON PV.mgr_id = M.mgr_id
                 INNER JOIN mc.t_mgr_types MT
                   ON M.mgr_type_id = MT.mgr_type_id
                 INNER JOIN TmpManagerList U
                   ON M.mgr_name = U.manager_name
            WHERE PT.param_name = 'mgractive' AND
                  PV.value <> _newValue AND
                  MT.mgr_type_active > 0
        LOOP

            _infoData := format('%-22s %-15s %-20s %-25s %-25s',
                                    _previewData.State_Change_Preview,
                                    _previewData.Parameter_Name,
                                    _previewData.manager_name,
                                    _previewData.Manager_Type,
                                    _previewData.control_from_website
                            );

            RAISE INFO '%', _infoData;

        END LOOP;

        _message := format('Would set %s managers to %s; see the Output window for details',
                            _countToUpdate,
                            _activeStateDescription);
</code>```

Example usage (complete procedure is in the PNNL-Comp-Mass-Spec/DBSchema_PgSQL_DMS repo on GitHub):

CALL mc.EnableDisableManagers(
    _enable => 1,
    _managerTypeID => 11,
    _managerNameList => 'Pub-80%',
    _infoOnly => 1,
    _includeDisabled => 0
);
```

<p>Example results:</p>

```+-----------------------------------+-------------+
|    _message                       | _returnCode |
+-----------------------------------+-------------+
| Would set 8 managers to Active;   |             |
| see the Output window for details |             |
+-----------------------------------+-------------+
```

<p>Output window contents:</p>

```State Change Preview   Parameter Name  Manager Name         Manager Type              Enabled (control_from_website=1)
False --> True         mgractive       Pub-80-1             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-2             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-3             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-4             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-5             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-6             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-7             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-8             Analysis Tool Manager     1
```

Body:
I created a stored procedure in PostgreSQL 11 to perform CRUD operation, and it works fine for 1. Create 2. Update 3. Delete, but while I run read command by passing Condition = 4 to select a result set, I get below error.

I have used PostgreSQL function to get result set it works for me, but I need to get result using the PostgreSQL stored procedure.

Here is my code for stored procedure:

CREATE OR REPLACE PROCEDURE public.testSpCrud(
    fnam text,
    lnam text,
    id integer,
    condition integer)
LANGUAGE 'plpgsql'

AS $BODY$
declare
    countOfDisc int;
BEGIN
if condition=1 then

INSERT INTO public.employee(
    employeeid, lname, fname, securitylevel, employeepassword, hphonearea, hphone, cphonearea, cphone, street, city, state, zipcode, extzip, name, email, groomerid, type, commission, inactive, carrierid, notoallemployees, languageid, isdogwalker, ispetsitter, ismobilegroomer, ssma_timestamp)
    VALUES (4,  'Test', 'Test', 2, 2, 32, 32, 32, 32, 32, 32,32, 32, 32, 22, 22, 2, 2, 2, false, 223,true, 223, true, true, true, '2019-08-27');
end if;
 if condition =2 then
    delete from Employee where employeeid=id;
    end if;
     if condition =3 then
    update Employee set fname='Test' where employeeid=id;
    end if;
     if condition =4 then
         Select * from Employee;
    end if;
    END;
$BODY$;

ERROR: query has no destination for result data
HINT: If you want to discard the results of a SELECT, use PERFORM instead.
CONTEXT: PL/pgSQL function testspcrud(text,text,integer,integer) line 22 at SQL statement
SQL state: 42601

Body:
Most people will suggest that when migrating MS SQL Server stored procedures to PostgreSQL, if the procedure returns a set of data (rows and columns), you change the stored procedure into a function, since functions, by nature, return sets of data.  However, as of Postgres 11, you can return result sets from a PostgreSQL Procedure using cursors, though it can be tedious to iterate over the results.

The following demonstrates how to return a set of data from a PostgreSQL procedure using an INOUT cursor:

CREATE OR REPLACE PROCEDURE test_get_data_single(
    _itemID int,
    INOUT _message text = '',
    INOUT _result_one refcursor = 'rs_resultone',
    INOUT _returnCode text = '')
LANGUAGE plpgsql
AS
$$
BEGIN
    _message := 'Test message for item ' || COALESCE(_itemID, 0);
    _returnCode := '';

  open _result_one for
    SELECT *
    FROM (values (1,2,3, 'fruit', current_timestamp - INTERVAL '5 seconds'),
                 (4,5,6, 'veggie', current_timestamp)) as t(a,b,c,d,e);

END;
$$;

To use, call the procedure within a transaction

BEGIN;
    CALL test_get_data_single(1);
    FETCH ALL FROM "rs_resultone";
COMMIT;

PostgreSQL also supports using Begin / End:

BEGIN;
    CALL test_get_data_single(2);
    FETCH ALL FROM "rs_resultone";
END;

Example results from DBeaver

+--------------------------+--------------+-------------+
|    _message              | _result_one  | _returncode |
+--------------------------+--------------+-------------+
| Test message for item 2  | rs_resultone |             |
+--------------------------+--------------+-------------+

+---+---+---+--------+---------------------|
| a | b | c | d      | e                   |
+---+---+---+--------+---------------------|
| 1 | 2 | 3 | fruit  | 2020-02-15 10:12:09 |
| 4 | 5 | 6 | veggie | 2020-02-15 10:12:09 |
+---+---+---+--------+---------------------|

For more advanced handling of the results, use an anonymous code block to iterate over the results

DO
$$
DECLARE
    _message text = '';
    _returnCode text = '';
    _result_one refcursor;
    _result_single refcursor;
    _currentRow record;
    _i int;
BEGIN

    CALL test_get_data_single(1, _message => _message, _result_one => _result_single, _returnCode => _returnCode);

    RAISE info 'Cursor _result_single from test_get_data_single: %', _result_single;

    _i := 0;
    WHILE TRUE
    Loop
        FETCH NEXT FROM _result_single INTO _currentRow;

        IF _currentRow IS NULL Then
            EXIT;
        END IF;

        _i := _i + 1;
        RAISE info '%, array: %', _i, _currentRow;
        RAISE info '%, values: %  %  %  %', _i, _currentRow.a, _currentRow.b, _currentRow.c, _currentRow.d;
    END LOOP;

End
$$;

Example results from DBeaver (look in the Server Output, opened with Ctrl+Shift+O):

Cursor _result_single from test_get_data_single: <unnamed portal 261>
1, array: (1,2,3,fruit,"2020-02-14 17:19:29.612822-08")
1, values: 1  2  3  fruit
2, array: (4,5,6,veggie,"2020-02-14 17:19:34.612822-08")
2, values: 4  5  6  veggie

Example results from psql:

INFO:  Cursor _result_single from test_get_data_single: <unnamed portal 4>
INFO:  1, array: (1,2,3,fruit,"2020-02-14 17:22:50.81671-08")
INFO:  1, values: 1  2  3  fruit
INFO:  2, array: (4,5,6,veggie,"2020-02-14 17:22:55.81671-08")
INFO:  2, values: 4  5  6  veggie

A procedure can also return two result sets, using separate refcursor arguments:

CREATE OR REPLACE PROCEDURE test_get_data(
    _itemID int,
    INOUT _message TEXT = '',
    INOUT _result_one refcursor = 'rs_resultone',
    INOUT _result_two refcursor = 'rs_resulttwo',
    INOUT _returnCode TEXT = '')
LANGUAGE plpgsql
AS
$$
BEGIN
    _message := 'Test message for item ' || COALESCE(_itemID, 0);
    _returnCode := '';

  open _result_one for
    SELECT *
    FROM (values (1,2,3, 'fruit', current_timestamp - INTERVAL '5 seconds'), (4,5,6, 'veggie', current_timestamp)) as t(a,b,c,d,e);

  open _result_two for
    SELECT *
    FROM (values ('one'), ('two'), ('three'), ('four')) as p(name);

END;
$$;

Retrieve results with:

BEGIN;
    CALL test_get_data(1);
    FETCH ALL FROM "rs_resultone";
    FETCH ALL FROM "rs_resulttwo";
END;

Or use an expanded anonymous code block for viewing the results

DO
$$
DECLARE
    _message text = '';
    _returnCode text = '';
    _result_one refcursor;
    _result_two refcursor;
    _result_single refcursor;
    _currentRow record;
    _i int;
BEGIN

    CALL test_get_data(1, _message => _message, _result_one => _result_one, _result_two => _result_two, _returnCode => _returnCode);

    RAISE info '%', _message;

    RAISE info '';
    RAISE info 'Cursor _result_one: %', _result_one;

    _i := 0;
    WHILE TRUE
    Loop
        FETCH NEXT FROM _result_one INTO _currentRow;

        IF _currentRow IS NULL Then
            EXIT;
        END IF;

        _i := _i + 1;
        RAISE info '%, array: %', _i, _currentRow;
        RAISE info '%, values: %  %  %  %', _i, _currentRow.a, _currentRow.b, _currentRow.c, _currentRow.d;

    END LOOP;

    RAISE info '';
    RAISE info 'Cursor _result_two: %', _result_two;

    _i := 0;
    WHILE TRUE
    Loop
        FETCH NEXT FROM _result_two INTO _currentRow;

        IF _currentRow IS NULL Then
            EXIT;
        END IF;

        _i := _i + 1;
       RAISE info '%: %', _i, _currentRow;

    END LOOP;
End
$$;

Output:

Test message for item 1

Cursor _result_one: <unnamed portal 263>
1, array: (1,2,3,fruit,"2020-02-14 17:25:06.528551-08")
1, values: 1  2  3  fruit
2, array: (4,5,6,veggie,"2020-02-14 17:25:11.528551-08")
2, values: 4  5  6  veggie

Cursor _result_two: <unnamed portal 264>
1: (one)
2: (two)
3: (three)
4: (four)

The alternative design pattern, especially for procedures that normally add/update data, but for where you occasionally want to preview results is to use RAISE INFO statements.  For example:

    If _infoOnly <> 0 Then

        _infoHead := format('%-22s %-15s %-20s %-25s %-25s',
                            'State Change Preview',
                            'Parameter Name',
                            'Manager Name',
                            'Manager Type',
                            'Enabled (control_from_website=1)'
                        );

        RAISE INFO '%', _infoHead;

        FOR _previewData IN
            SELECT PV.value || ' --> ' || _newValue AS State_Change_Preview,
                   PT.param_name AS Parameter_Name,
                   M.mgr_name AS manager_name,
                   MT.mgr_type_name AS Manager_Type,
                   M.control_from_website
            FROM mc.t_param_value PV
                 INNER JOIN mc.t_param_type PT
                   ON PV.type_id = PT.param_id
                 INNER JOIN mc.t_mgrs M
                   ON PV.mgr_id = M.mgr_id
                 INNER JOIN mc.t_mgr_types MT
                   ON M.mgr_type_id = MT.mgr_type_id
                 INNER JOIN TmpManagerList U
                   ON M.mgr_name = U.manager_name
            WHERE PT.param_name = 'mgractive' AND
                  PV.value <> _newValue AND
                  MT.mgr_type_active > 0
        LOOP

            _infoData := format('%-22s %-15s %-20s %-25s %-25s',
                                    _previewData.State_Change_Preview,
                                    _previewData.Parameter_Name,
                                    _previewData.manager_name,
                                    _previewData.Manager_Type,
                                    _previewData.control_from_website
                            );

            RAISE INFO '%', _infoData;

        END LOOP;

        _message := format('Would set %s managers to %s; see the Output window for details',
                            _countToUpdate,
                            _activeStateDescription);

Example usage (complete procedure is in the PNNL-Comp-Mass-Spec/DBSchema_PgSQL_DMS repo on GitHub):

CALL mc.EnableDisableManagers(
    _enable => 1,
    _managerTypeID => 11,
    _managerNameList => 'Pub-80%',
    _infoOnly => 1,
    _includeDisabled => 0
);

Example results:

+-----------------------------------+-------------+
|    _message                       | _returnCode |
+-----------------------------------+-------------+
| Would set 8 managers to Active;   |             |
| see the Output window for details |             |
+-----------------------------------+-------------+

Output window contents:

State Change Preview   Parameter Name  Manager Name         Manager Type              Enabled (control_from_website=1)
False --> True         mgractive       Pub-80-1             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-2             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-3             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-4             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-5             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-6             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-7             Analysis Tool Manager     1
False --> True         mgractive       Pub-80-8             Analysis Tool Manager     1


来源: stackexchange

问:
ERROR! Unexpected Exception, this is probably a bug: unhashable type: 'AnsibleMapping'
I have been trying to get my first trial with templating with Ansible to work and I am stopped by this following exception. As far as I can see, I think I have maintained the indentation well and also validated the yml file. I don't know where to go from here, help pls! Below is the yml file followed by the exception I saw after ran the playbook.

```<code>
---

- name: run these tasks on the host
  hosts:
    testhost:
    testhost1: "172.16.201.163"
  vars:
    ansible_port: 22
  tasks:

    - name: Templating
      template:
        dest: /etc/my_test.conf
        owner: root
        src: my_test.j2
      become: true
</code>```

The output from the run

```<code>ERROR! Unexpected Exception, this is probably a bug: unhashable type: 'AnsibleMapping'
the full traceback was:

Traceback (most recent call last):
  File "/usr/local/bin/ansible-playbook", line 118, in <module>
    exit_code = cli.run()
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/cli/playbook.py", line 122, in run
    results = pbex.run()
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/executor/playbook_executor.py", line 106, in run
    all_vars = self._variable_manager.get_vars(play=play)
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/vars/manager.py", line 185, in get_vars
    include_delegate_to=include_delegate_to,
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/vars/manager.py", line 470, in _get_magic_variables
    variables['ansible_play_hosts_all'] = [x.name for x in self._inventory.get_hosts(pattern=pattern, ignore_restrictions=True)]
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/inventory/manager.py", line 358, in get_hosts
    if pattern_hash not in self._hosts_patterns_cache:
TypeError: unhashable type: 'AnsibleMapping'

</code>```

答:
There are at minimum two things wrong with the playbook you posted:

hosts: is a dict, but should not be

testhost: has a null value

Reading the fine manual shows that hosts: should be a string, or list[str] but may not be a dict. Perhaps what you are trying to accomplish is best achieved via an inventory file, or dynamic inventory plugin/script

ContentLicense: CC BY-SA 4.0

Body:
I have been trying to get my first trial with templating with Ansible to work and I am stopped by this following exception. As far as I can see, I think I have maintained the indentation well and also validated the yml file. I don't know where to go from here, help pls! Below is the yml file followed by the exception I saw after ran the playbook.

---

- name: run these tasks on the host
  hosts:
    testhost:
    testhost1: "172.16.201.163"
  vars:
    ansible_port: 22
  tasks:

    - name: Templating
      template:
        dest: /etc/my_test.conf
        owner: root
        src: my_test.j2
      become: true

The output from the run

ERROR! Unexpected Exception, this is probably a bug: unhashable type: 'AnsibleMapping'
the full traceback was:

Traceback (most recent call last):
  File "/usr/local/bin/ansible-playbook", line 118, in <module>
    exit_code = cli.run()
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/cli/playbook.py", line 122, in run
    results = pbex.run()
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/executor/playbook_executor.py", line 106, in run
    all_vars = self._variable_manager.get_vars(play=play)
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/vars/manager.py", line 185, in get_vars
    include_delegate_to=include_delegate_to,
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/vars/manager.py", line 470, in _get_magic_variables
    variables['ansible_play_hosts_all'] = [x.name for x in self._inventory.get_hosts(pattern=pattern, ignore_restrictions=True)]
  File "/usr/local/Cellar/ansible/2.7.9/libexec/lib/python3.7/site-packages/ansible/inventory/manager.py", line 358, in get_hosts
    if pattern_hash not in self._hosts_patterns_cache:
TypeError: unhashable type: 'AnsibleMapping'


问:
Why is my Apache Ignite persistent store remaining locked?
I have an application that uses Apache Ignite as a single node cluster.  That is, Ignite is started and stopped by the application and its lifecycle matches the application.

The Ignite caches have both persistent storage and read-through enabled.  So,

First call to cache.get() --> nothing in cache, reads through via CacheAdapter to backing store (an Oracle database) and loads the entry into the cache.

Subsequent call to cache.get() -> returns from cache

Application bounces, the call cache.get()  --> returns from cache (from persistent store).  Key point is that it does not read through to the backing store after an application bounce!

All this seems to be working wonderfully.  Here is my problem: sometimes (fairly often) when the application is bounced or redeployed, the persistent store data directory remains locked as far as Apache Ignite is concerned.  As a result, Ignite silently creates a new, empty persistent store, which defeats the whole purpose of persistent storage.

Our data directory currently looks like this:

```<code>-sh-4.2$ pwd
/myapp/oracle/user_projects/domains/myapp_inst/igniteCache/myserver/data
-sh-4.2$ ls -ltr
total 48
drwxr-x---. 10 mygroup mygroup 4096 Jan  9 16:25 node00-7c02d9ab-7ef3-4d01-8ebd-d1184fa281a2
drwxr-x---. 10 mygroup mygroup 4096 Jan  9 17:28 node01-06a5d059-1b62-4ac2-84bf-5325deac8138
drwxr-x---. 10 mygroup mygroup 4096 Feb  4 15:39 node02-ba720d52-570a-448c-9109-75687ee664e7
drwxr-x---. 10 mygroup mygroup 4096 Feb  5 12:16 node03-d2c521aa-e0ee-471b-ad16-08af382a1e3d
drwxr-x---. 10 mygroup mygroup 4096 Feb  6 17:44 node04-505e754e-a3d3-48b1-a759-d5ec8867dc96
drwxr-x---. 10 mygroup mygroup 4096 Feb  6 18:23 node05-ec0f89e3-bfe5-4bb6-87da-302951439f66
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:41 node06-5b9dc33a-42f6-4f1c-8d57-14d5ddb30dc5
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:43 node07-47aacde5-2598-4a85-9383-761e569bb1d1
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:47 node08-0374a51d-4b90-4e5a-9465-adabc900ea0b
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:52 node09-610c69c6-35e0-4d74-90db-6be09bb77659
-rw-r-----.  1 mygroup mygroup   41 Feb 13 17:00 lock
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 17:00 node10-f115d95b-7b76-41e0-bd32-966030331c9c
</code>```

There should only be one "nodeXX..." directory above.

Questions

Is there anything I can do my application to ensure that, whatever the failure, the persistent store locks are released?

Is there anything I can do on application startup to tell Ignite to break or delete the lock and not create a new, empty store every time?

Is there anything I can do in my application to tell Ignite that this persistent store is local to the node and that, therefore, locks aren't necessary?

Really, anything I can do to get around this behavior would be helpful.

答:
Please set Ignite ConsistentId:
igniteCfg.setConsistentId("My_Node_Id" + id);
https://apacheignite.readme.io/docs/distributed-persistent-store#section-persistence-path-management

in this case, ignite will try to acquire file lock and wait for 10 seconds, if it fails to acquire it, it won't create a new folder, but fail with an exception.

Body:
I have an application that uses Apache Ignite as a single node cluster.  That is, Ignite is started and stopped by the application and its lifecycle matches the application.

The Ignite caches have both persistent storage and read-through enabled.  So,

First call to cache.get() --> nothing in cache, reads through via CacheAdapter to backing store (an Oracle database) and loads the entry into the cache.

Subsequent call to cache.get() -> returns from cache

Application bounces, the call cache.get()  --> returns from cache (from persistent store).  Key point is that it does not read through to the backing store after an application bounce!

All this seems to be working wonderfully.  Here is my problem: sometimes (fairly often) when the application is bounced or redeployed, the persistent store data directory remains locked as far as Apache Ignite is concerned.  As a result, Ignite silently creates a new, empty persistent store, which defeats the whole purpose of persistent storage.

Our data directory currently looks like this:

-sh-4.2$ pwd
/myapp/oracle/user_projects/domains/myapp_inst/igniteCache/myserver/data
-sh-4.2$ ls -ltr
total 48
drwxr-x---. 10 mygroup mygroup 4096 Jan  9 16:25 node00-7c02d9ab-7ef3-4d01-8ebd-d1184fa281a2
drwxr-x---. 10 mygroup mygroup 4096 Jan  9 17:28 node01-06a5d059-1b62-4ac2-84bf-5325deac8138
drwxr-x---. 10 mygroup mygroup 4096 Feb  4 15:39 node02-ba720d52-570a-448c-9109-75687ee664e7
drwxr-x---. 10 mygroup mygroup 4096 Feb  5 12:16 node03-d2c521aa-e0ee-471b-ad16-08af382a1e3d
drwxr-x---. 10 mygroup mygroup 4096 Feb  6 17:44 node04-505e754e-a3d3-48b1-a759-d5ec8867dc96
drwxr-x---. 10 mygroup mygroup 4096 Feb  6 18:23 node05-ec0f89e3-bfe5-4bb6-87da-302951439f66
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:41 node06-5b9dc33a-42f6-4f1c-8d57-14d5ddb30dc5
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:43 node07-47aacde5-2598-4a85-9383-761e569bb1d1
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:47 node08-0374a51d-4b90-4e5a-9465-adabc900ea0b
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 15:52 node09-610c69c6-35e0-4d74-90db-6be09bb77659
-rw-r-----.  1 mygroup mygroup   41 Feb 13 17:00 lock
drwxr-x---. 10 mygroup mygroup 4096 Feb 13 17:00 node10-f115d95b-7b76-41e0-bd32-966030331c9c

There should only be one "nodeXX..." directory above.

Questions

Is there anything I can do my application to ensure that, whatever the failure, the persistent store locks are released?

Is there anything I can do on application startup to tell Ignite to break or delete the lock and not create a new, empty store every time?

Is there anything I can do in my application to tell Ignite that this persistent store is local to the node and that, therefore, locks aren't necessary?

Really, anything I can do to get around this behavior would be helpful.


问:
ERROR: While executing gem ... (Gem::FilePermissionError)
I have checked all the other similar answers and none was exactly like mine, neither did any of those solutions work for me.

gem environment and sudo gem environment give the same result:

```<code>RubyGems Environment:
  - RUBYGEMS VERSION: 1.5.3
  - RUBY VERSION: 1.8.7 (2011-12-28 patchlevel 357) [x86_64-linux]
  - INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8
  - RUBY EXECUTABLE: /usr/local/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/bin
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-linux
  - GEM PATHS:
     - /usr/local/lib/ruby/gems/1.8
     - /home/ava/.gem/ruby/1.8
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :benchmark => false
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - http://rubygems.org/
</code>```

rvm -v : rvm 1.22.3

ruby -v : ruby 1.8.7

OSX 10.8.4

echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/ava/.rvm/bin:/home/ava/bin

gem install <gem-name> gives

```<code>ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions into the /usr/local/lib/ruby/gems/1.8 directory.
</code>```

whereas I am able to install the same via sudo. What am I doing wrong?

UPDATE:

As per comments and this post, I ran following:

rvm implode and then re installed the stable version.
rvm install 1.9.3 or any other ruby installation fails with

```<code>Error running '__rvm_make -j24',
please read /home/ava/.rvm/log/log/1378418790_ruby-1.9.3-p194/make.log
There has been an error while running make. Halting the installation.
</code>```

make.log

```<code>    [2013-09-05 22:06:48] make
current path: /home/ava/.rvm/src/ruby-1.9.3-p194
command(2): make -j24
        CC = gcc
        LD = ld
        LDSHARED = gcc -shared
        CFLAGS = -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Werror-implicit-function-declaration  -fPIC
        XCFLAGS = -include ruby/config.h -include ruby/missing.h -fvisibility=hidden -DRUBY_EXPORT
        CPPFLAGS =   -I. -I.ext/include/x86_64-linux -I./include -I.
        DLDFLAGS = -Wl,-soname,libruby.so.1.9
        SOLIBS = -lpthread -lrt -ldl -lcrypt -lm
compiling main.c
compiling dmydln.c
compiling dmyencoding.c
compiling version.c
compiling miniprelude.c
compiling array.c
compiling bignum.c
compiling class.c
compiling compar.c
compiling complex.c
compiling dir.c
compiling dln_find.c
compiling enum.c
compiling enumerator.c
compiling error.c
compiling eval.c
compiling load.c
compiling proc.c
compiling file.c
:
:
:
In file included from ossl.h:213,
                 from ossl_pkcs5.c:5:
openssl_missing.h:71: error: conflicting types for ‘HMAC_CTX_copy’
/usr/local/include/openssl/hmac.h:102: error: previous declaration of ‘HMAC_CTX_copy’ was here
openssl_missing.h:95: error: conflicting types for ‘EVP_CIPHER_CTX_copy’
/usr/local/include/openssl/evp.h:459: error: previous declaration of ‘EVP_CIPHER_CTX_copy’ was here
make[2]: *** [ossl_pkcs5.o] Error 1
In file included from ossl.h:213,
                 from ossl_x509req.c:11:
:
:
:
</code>```

答:
I run into a similar problem on my Mac while trying to install watchr package

ERROR:  While executing gem ... (Gem::FilePermissionError)

Somehow running sudo every time I need to install a package felt excessive. I have rbenv installed so I set global ruby version like this

```<code>rbenv global 2.6.5
</code>```

Then simply installed the package I wanted. In my case the command is

```<code>gem install watchr
</code>```

ContentLicense: CC BY-SA 3.0

Body:
I have checked all the other similar answers and none was exactly like mine, neither did any of those solutions work for me.

gem environment and sudo gem environment give the same result:

RubyGems Environment:
  - RUBYGEMS VERSION: 1.5.3
  - RUBY VERSION: 1.8.7 (2011-12-28 patchlevel 357) [x86_64-linux]
  - INSTALLATION DIRECTORY: /usr/local/lib/ruby/gems/1.8
  - RUBY EXECUTABLE: /usr/local/bin/ruby
  - EXECUTABLE DIRECTORY: /usr/local/bin
  - RUBYGEMS PLATFORMS:
    - ruby
    - x86_64-linux
  - GEM PATHS:
     - /usr/local/lib/ruby/gems/1.8
     - /home/ava/.gem/ruby/1.8
  - GEM CONFIGURATION:
     - :update_sources => true
     - :verbose => true
     - :benchmark => false
     - :backtrace => false
     - :bulk_threshold => 1000
  - REMOTE SOURCES:
     - http://rubygems.org/

rvm -v : rvm 1.22.3

ruby -v : ruby 1.8.7

OSX 10.8.4

echo $PATH
/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/ava/.rvm/bin:/home/ava/bin

gem install <gem-name> gives

ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions into the /usr/local/lib/ruby/gems/1.8 directory.

whereas I am able to install the same via sudo. What am I doing wrong?

UPDATE:

As per comments and this post, I ran following:

rvm implode and then re installed the stable version.
rvm install 1.9.3 or any other ruby installation fails with

Error running '__rvm_make -j24',
please read /home/ava/.rvm/log/log/1378418790_ruby-1.9.3-p194/make.log
There has been an error while running make. Halting the installation.

make.log

    [2013-09-05 22:06:48] make
current path: /home/ava/.rvm/src/ruby-1.9.3-p194
command(2): make -j24
        CC = gcc
        LD = ld
        LDSHARED = gcc -shared
        CFLAGS = -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Werror-implicit-function-declaration  -fPIC
        XCFLAGS = -include ruby/config.h -include ruby/missing.h -fvisibility=hidden -DRUBY_EXPORT
        CPPFLAGS =   -I. -I.ext/include/x86_64-linux -I./include -I.
        DLDFLAGS = -Wl,-soname,libruby.so.1.9
        SOLIBS = -lpthread -lrt -ldl -lcrypt -lm
compiling main.c
compiling dmydln.c
compiling dmyencoding.c
compiling version.c
compiling miniprelude.c
compiling array.c
compiling bignum.c
compiling class.c
compiling compar.c
compiling complex.c
compiling dir.c
compiling dln_find.c
compiling enum.c
compiling enumerator.c
compiling error.c
compiling eval.c
compiling load.c
compiling proc.c
compiling file.c
:
:
:
In file included from ossl.h:213,
                 from ossl_pkcs5.c:5:
openssl_missing.h:71: error: conflicting types for ‘HMAC_CTX_copy’
/usr/local/include/openssl/hmac.h:102: error: previous declaration of ‘HMAC_CTX_copy’ was here
openssl_missing.h:95: error: conflicting types for ‘EVP_CIPHER_CTX_copy’
/usr/local/include/openssl/evp.h:459: error: previous declaration of ‘EVP_CIPHER_CTX_copy’ was here
make[2]: *** [ossl_pkcs5.o] Error 1
In file included from ossl.h:213,
                 from ossl_x509req.c:11:
:
:
:

Body:
I run into a similar problem on my Mac while trying to install watchr package

ERROR:  While executing gem ... (Gem::FilePermissionError)

Somehow running sudo every time I need to install a package felt excessive. I have rbenv installed so I set global ruby version like this

rbenv global 2.6.5

Then simply installed the package I wanted. In my case the command is

gem install watchr


问:
Why am I getting an IllegalStateException when stopping MediaRecorder?
To get a better understanding of audio recording and playback in Android, I've implemented a clone of the code in the android dev tutorial https://developer.android.com/guide/topics/media/mediarecorder#sample-code

No errors occur upon starting the recording, however, I have yet to verify if any recording is actually taking place. Then when I stop recording, the app crashes to the previous activity and on a subsequent attempt the "app keeps crashing" dialog pops up and the app exits.

I have <uses-permission android:name="android.permission.RECORD_AUDIO" /> in the AndroidManifest

```<code>private void onRecord(boolean start) {
        if (start) {
            startRecording();
        } else {
            stopRecording();   // Line 53 //
        }
    }

private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        System.out.println(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            //e.printStackTrace();
        }
    }

private void stopRecording() {
        recorder.stop();       // Line 98 //
        recorder.release();
        recorder = null;
    }

class RecordButton extends AppCompatButton {
        boolean mStartRecording = true;

        OnClickListener clicker = new OnClickListener() {
            public void onClick(View v) {
                onRecord(mStartRecording);
                if(mStartRecording) {
                    setText(R.string.stop_recording);
                } else {
                    setText(R.string.start_recording);
                }
                mStartRecording = !mStartRecording;
            }
        };

        public RecordButton(Context ctx){
            super(ctx);
            setText(R.string.start_recording);
            setOnClickListener(clicker);
        }
    }
</code>```

Logcat output:

```<code>2020-02-14 10:57:09.789 23619-23619/? E/Zygote: accessInfo : 1
2020-02-14 10:57:09.820 23619-23619/? E/.xxxxxx.xxxxxx: Unknown bits set in runtime_flags: 0x8000
2020-02-14 10:57:12.925 23619-23619/xx.xxxxxxx.xxxxxx.xxxxxxx E/MediaRecorder: stop called in an invalid state: 8
2020-02-14 10:57:12.927 23619-23619/xx.xxxxxxx.xxxxxx.xxxxxxx E/AndroidRuntime: FATAL EXCEPTION: main
    Process: xx.xxxxxxx.xxxxxx.xxxxxxx, PID: 23619
    java.lang.IllegalStateException
        at android.media.MediaRecorder._stop(Native Method)
        at android.media.MediaRecorder.stop(MediaRecorder.java:1440)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.stopRecording(RecordActivity.java:98)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.onRecord(RecordActivity.java:53)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.access$000(RecordActivity.java:21)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity$RecordButton$1.onClick(RecordActivity.java:108)
        at android.view.View.performClick(View.java:7866)
        at android.widget.TextView.performClick(TextView.java:14952)
        at android.view.View.performClickInternal(View.java:7839)
        at android.view.View.access$3600(View.java:886)
        at android.view.View$PerformClick.run(View.java:29363)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7811)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)
</code>```

I can provide any relevant additional code or details if needed

EDIT
Permission is requested with the following:

```<code>    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case REQUEST_RECORD_AUDIO_PERMISSION:
                permissionToRecordAccepted  = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                break;
        }
        if (!permissionToRecordAccepted ) finish();

    }
</code>```

and inside onCreate():

ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);

EDIT 2 *
I've verified that the audio recording file is being created but is 0 B in size

答:
Media Player

in the below flowchart, stop() valid states are {Prepared, Started, Stopped, Paused, PlaybackCompleted}. other states(Idle,Initialized,Error) are NOT valid states in order to call stop(). otherwise, IllegalStateException thrown.

Therefore, for Ensure we should set states listeners for the MediaPlayer. Because the Prepared state is initialized earlier than by setOnPreparedListener for player we can safely stop the player.

```<code>...
boolean isPrepared = false;
...
recorder.setOnPreparedListener ....
{
...
isPrepared = true;
...
}
...
private void stopRecording() {
    if(isPrepared){
        player.stop();
        ...
    }
}
</code>```

I made the code summarized for better understanding.

Media Recorder

in the below flowchart, stop() is available only if you are in recording state. otherwise, calling stop() throws IllegalStateException.

in order to safely stop or release recorder resources, we have to make sure the recorder has been started.

```<code>recorder.start();   // Recording is now started
</code>```

for your specific code

```<code>boolean isRecording = false;
private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        System.out.println(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
            recorder.start();
            isRecording = true;
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            //e.printStackTrace();
        }
}
....
private void stopRecording() {
    if(isRecording){
        recorder.stop();
    }
    recorder.reset();   // You can reuse the object by going back to setAudioSource() step
    recorder.release(); // Now the object cannot be reused
    isRecording = false;
}
</code>```

if we are in the recording state stop it then release it otherwise just release it.

Body:
To get a better understanding of audio recording and playback in Android, I've implemented a clone of the code in the android dev tutorial https://developer.android.com/guide/topics/media/mediarecorder#sample-code

No errors occur upon starting the recording, however, I have yet to verify if any recording is actually taking place. Then when I stop recording, the app crashes to the previous activity and on a subsequent attempt the "app keeps crashing" dialog pops up and the app exits.

I have <uses-permission android:name="android.permission.RECORD_AUDIO" /> in the AndroidManifest

private void onRecord(boolean start) {
        if (start) {
            startRecording();
        } else {
            stopRecording();   // Line 53 //
        }
    }

private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        System.out.println(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            //e.printStackTrace();
        }
    }

private void stopRecording() {
        recorder.stop();       // Line 98 //
        recorder.release();
        recorder = null;
    }

class RecordButton extends AppCompatButton {
        boolean mStartRecording = true;

        OnClickListener clicker = new OnClickListener() {
            public void onClick(View v) {
                onRecord(mStartRecording);
                if(mStartRecording) {
                    setText(R.string.stop_recording);
                } else {
                    setText(R.string.start_recording);
                }
                mStartRecording = !mStartRecording;
            }
        };

        public RecordButton(Context ctx){
            super(ctx);
            setText(R.string.start_recording);
            setOnClickListener(clicker);
        }
    }

Logcat output:

2020-02-14 10:57:09.789 23619-23619/? E/Zygote: accessInfo : 1
2020-02-14 10:57:09.820 23619-23619/? E/.xxxxxx.xxxxxx: Unknown bits set in runtime_flags: 0x8000
2020-02-14 10:57:12.925 23619-23619/xx.xxxxxxx.xxxxxx.xxxxxxx E/MediaRecorder: stop called in an invalid state: 8
2020-02-14 10:57:12.927 23619-23619/xx.xxxxxxx.xxxxxx.xxxxxxx E/AndroidRuntime: FATAL EXCEPTION: main
    Process: xx.xxxxxxx.xxxxxx.xxxxxxx, PID: 23619
    java.lang.IllegalStateException
        at android.media.MediaRecorder._stop(Native Method)
        at android.media.MediaRecorder.stop(MediaRecorder.java:1440)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.stopRecording(RecordActivity.java:98)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.onRecord(RecordActivity.java:53)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity.access$000(RecordActivity.java:21)
        at xx.xxxxxxx.xxxxxx.xxxxxxx.RecordActivity$RecordButton$1.onClick(RecordActivity.java:108)
        at android.view.View.performClick(View.java:7866)
        at android.widget.TextView.performClick(TextView.java:14952)
        at android.view.View.performClickInternal(View.java:7839)
        at android.view.View.access$3600(View.java:886)
        at android.view.View$PerformClick.run(View.java:29363)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:237)
        at android.app.ActivityThread.main(ActivityThread.java:7811)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1076)

I can provide any relevant additional code or details if needed

EDIT
Permission is requested with the following:

    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case REQUEST_RECORD_AUDIO_PERMISSION:
                permissionToRecordAccepted  = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                break;
        }
        if (!permissionToRecordAccepted ) finish();

    }

and inside onCreate():

ActivityCompat.requestPermissions(this, permissions, REQUEST_RECORD_AUDIO_PERMISSION);

EDIT 2 *
I've verified that the audio recording file is being created but is 0 B in size

Body:
Media Player

in the below flowchart, stop() valid states are {Prepared, Started, Stopped, Paused, PlaybackCompleted}. other states(Idle,Initialized,Error) are NOT valid states in order to call stop(). otherwise, IllegalStateException thrown.

Therefore, for Ensure we should set states listeners for the MediaPlayer. Because the Prepared state is initialized earlier than by setOnPreparedListener for player we can safely stop the player.

...
boolean isPrepared = false;
...
recorder.setOnPreparedListener ....
{
...
isPrepared = true;
...
}
...
private void stopRecording() {
    if(isPrepared){
        player.stop();
        ...
    }
}

I made the code summarized for better understanding.

Media Recorder

in the below flowchart, stop() is available only if you are in recording state. otherwise, calling stop() throws IllegalStateException.

in order to safely stop or release recorder resources, we have to make sure the recorder has been started.

recorder.start();   // Recording is now started

for your specific code

boolean isRecording = false;
private void startRecording() {
        recorder = new MediaRecorder();
        recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
        recorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        recorder.setOutputFile(fileName);
        System.out.println(fileName);
        recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);

        try {
            recorder.prepare();
            recorder.start();
            isRecording = true;
        } catch (IOException e) {
            Log.e(LOG_TAG, "prepare() failed");
            //e.printStackTrace();
        }
}
....
private void stopRecording() {
    if(isRecording){
        recorder.stop();
    }
    recorder.reset();   // You can reuse the object by going back to setAudioSource() step
    recorder.release(); // Now the object cannot be reused
    isRecording = false;
}

if we are in the recording state stop it then release it otherwise just release it.


问:
Cannot delete a file from s3 with boto3
I am trying to permanently delete a file from S3, using boto3. My buckets are not using versioning.

I have tried two ways:

def remove_aws_object(bucket_name, item_key):
    ''' Provide bucket name and item key, remove from S3
    '''
    s3_client = boto3.client('s3',
                             aws_access_key_id=AWS_ACCESS_KEY,
                             aws_secret_access_key=AWS_SECRET)
    delete = s3_client.delete_object(Bucket=bucket_name, Key=item_key)
    print(delete)
{'ResponseMetadata': {'RequestId': '61F3C195D373B0C5', 'HostId': 'pigcx1wtIN+Y8RU3zJKliWXcXrHXHzpdAOuGBL64x3V9YefQbWXPZi9B/9F', 'HTTPStatusCode': 204, 'HTTPHeaders': {'x-amz-id-2': 'pigcx1wtIN+Y8RU3zJKliWXcXrHXHzpdAOuGBL64x3V9YefQbWXPZi9B/9FLazUSsCds8f4=', 'x-amz-request-id': '61F3C195D373B0C5', 'date': 'Thu, 13 Feb 2020 09:07:50 GMT', 'server': 'AmazonS3'}, 'RetryAttempts': 0}}
```

<p>As well as via the Object:</p>

<pre class="lang-python prettyprint-override"><code>def remove_aws_object(bucket_name, item_key):
    ''' Provide bucket name and item key, remove from S3
    '''
    s3_client = boto3.resource('s3',
                             aws_access_key_id=AWS_ACCESS_KEY,
                             aws_secret_access_key=AWS_SECRET)

    my_object = s3_client.Object(bucket_name, item_key)
    a = my_object.delete()
    print(a)
    {'ResponseMetadata': {'RequestId': '6074B9CA870773CE', 'HostId': 'rQoK+x+xcjAw2T3DpTHMWQb4Gq6DzPJy2qFoFHQCYoGwb8/p7700+Nk+6gBIERN', 'HTTPStatusCode': 204, 'HTTPHeaders': {'x-amz-id-2': 'rQoK+x+xcjAw2TKK833DpTHMWQb4Gq6DzPJy2qFoFHQCYoGwb8/p7700+Nk+6gBIE', 'x-amz-request-id': '6074B9CA870773CE', 'date': 'Thu, 13 Feb 2020 12:02:36 GMT', 'x-amz-version-id': 'null', 'x-amz-delete-marker': 'true', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'DeleteMarker': True, 'VersionId': 'null'}
</code>```

Both methods work without error, but do not remove the file, I can still see it in the S3 console and I then have to manually delete it. Am I doing something wrong?

答:
To reproduce your situation, I did the following:

Created a new bucket in the Amazon S3 management console

Uploaded a file to the bucket via the management console

Used your code (first example) to delete the object

The object was successfully deleted.

So, the code is fine.

Title: Cannot delete a file from s3 with boto3

Body:
I am trying to permanently delete a file from S3, using boto3. My buckets are not using versioning.

I have tried two ways:

def remove_aws_object(bucket_name, item_key):
    ''' Provide bucket name and item key, remove from S3
    '''
    s3_client = boto3.client('s3',
                             aws_access_key_id=AWS_ACCESS_KEY,
                             aws_secret_access_key=AWS_SECRET)
    delete = s3_client.delete_object(Bucket=bucket_name, Key=item_key)
    print(delete)
{'ResponseMetadata': {'RequestId': '61F3C195D373B0C5', 'HostId': 'pigcx1wtIN+Y8RU3zJKliWXcXrHXHzpdAOuGBL64x3V9YefQbWXPZi9B/9F', 'HTTPStatusCode': 204, 'HTTPHeaders': {'x-amz-id-2': 'pigcx1wtIN+Y8RU3zJKliWXcXrHXHzpdAOuGBL64x3V9YefQbWXPZi9B/9FLazUSsCds8f4=', 'x-amz-request-id': '61F3C195D373B0C5', 'date': 'Thu, 13 Feb 2020 09:07:50 GMT', 'server': 'AmazonS3'}, 'RetryAttempts': 0}}

As well as via the Object:

def remove_aws_object(bucket_name, item_key):
    ''' Provide bucket name and item key, remove from S3
    '''
    s3_client = boto3.resource('s3',
                             aws_access_key_id=AWS_ACCESS_KEY,
                             aws_secret_access_key=AWS_SECRET)

    my_object = s3_client.Object(bucket_name, item_key)
    a = my_object.delete()
    print(a)
    {'ResponseMetadata': {'RequestId': '6074B9CA870773CE', 'HostId': 'rQoK+x+xcjAw2T3DpTHMWQb4Gq6DzPJy2qFoFHQCYoGwb8/p7700+Nk+6gBIERN', 'HTTPStatusCode': 204, 'HTTPHeaders': {'x-amz-id-2': 'rQoK+x+xcjAw2TKK833DpTHMWQb4Gq6DzPJy2qFoFHQCYoGwb8/p7700+Nk+6gBIE', 'x-amz-request-id': '6074B9CA870773CE', 'date': 'Thu, 13 Feb 2020 12:02:36 GMT', 'x-amz-version-id': 'null', 'x-amz-delete-marker': 'true', 'server': 'AmazonS3'}, 'RetryAttempts': 0}, 'DeleteMarker': True, 'VersionId': 'null'}

Both methods work without error, but do not remove the file, I can still see it in the S3 console and I then have to manually delete it. Am I doing something wrong?


问:
Using Angular Observable to subscribe to Session Storage key
I'm trying to accomplish what I had hoped would be a simple "look at the key in Session Storage and update it when it changes" scenario, but Observables really trip me up.

message$ = new Observable(observer => {
    observer.next(window.sessionStorage.getItem('message'));
});

ngOnInit() {
    this.message$.subscribe();
}
```
<p>And the message$ is bound to the HTML, pretty straightforward:</p>
<pre class="lang-html prettyprint-override"><code><p id="message">{{message$ | async}}</p>
</code>```

The Observable will output the text to the HTML if there's already value stored in 'message' but if there's no message on init and then it gets added, or the message value does exist and is updated, nothing happens. I'm obviously doing something wrong, and I would appreciate the insight of someone knowledgeable with Observables.

答:
Since you are using the async pipe, you don't need to subscribe in your component, you can take that out. AsyncPipe will handle the subscribe / unsubscribe behind the scenes.

Try using a subject instead.

```<code>// This is what will help you broadcast your message and push updates to subscribers.
message$ = new Subject();

// Anytime the "message" changes, you'll want to call this.
updateTheSubject() {
    this.message$.next(window.sessionStorage.getItem('message'));
}
</code>```

Your html template can remain unchanged.

https://rxjs-dev.firebaseapp.com/guide/subject

https://angular.io/api/common/AsyncPipe

Body:
I'm trying to accomplish what I had hoped would be a simple "look at the key in Session Storage and update it when it changes" scenario, but Observables really trip me up.

message$ = new Observable(observer => {
    observer.next(window.sessionStorage.getItem('message'));
});

ngOnInit() {
    this.message$.subscribe();
}

And the message$ is bound to the HTML, pretty straightforward:

{{message$ | async}}

The Observable will output the text to the HTML if there's already value stored in 'message' but if there's no message on init and then it gets added, or the message value does exist and is updated, nothing happens. I'm obviously doing something wrong, and I would appreciate the insight of someone knowledgeable with Observables.

Body:
Since you are using the async pipe, you don't need to subscribe in your component, you can take that out. AsyncPipe will handle the subscribe / unsubscribe behind the scenes.

Try using a subject instead.

// This is what will help you broadcast your message and push updates to subscribers.
message$ = new Subject();

// Anytime the "message" changes, you'll want to call this.
updateTheSubject() {
    this.message$.next(window.sessionStorage.getItem('message'));
}

Your html template can remain unchanged.

https://rxjs-dev.firebaseapp.com/guide/subject

https://angular.io/api/common/AsyncPipe


问:
Saving the output of a str_which loop in R
I work with a sheet of data that lists a variety of scientific publications. Rows are publications,
columns are a variety of metrics describing each publication (author name and position, Pubmed IDs, Date etc...)
I want to filter for publications for each author and extract parts of them. The caveat is the format:
all author names (5-80 per cell) are lumped together in one cell for each row.

I managed to solve this with the use of str_which, saving the coordinates for each author and later extract. This works only for manual use. When I try to automate this process using a loop to draw on a list of authors I fail to save the output.

I am at a bit of a loss on how to store the results without overwriting previous ones.

```<code>sampleDat <-
  data.frame(var1 = c("Doe J, Maxwell M, Kim HE", "Cronauer R, Carst W, Theobald U", "Theobald U, Hey B, Joff S"),
             var2 = c(1:3),
             var3 = c("2016-01", "2016-03", "2017-05"))
</code>```

list of names that I want the coordinates for

```<code>namesOfInterest <-
  list(c("Doe J", "Theobald U"))
</code>```

the manual extraction, requiring me to type the exact name and output object

```<code>Doe <- str_which(sampleDat$var1, "Doe J")
Theobald <- str_which(sampleDat$var1, "Theobald U")
</code>```

one of many attempts that does not replicate the manual version.

```<code>results <- c()

for (i in namesOfInterest) {
  results[i] <- str_which(sampleDat$var1, i)
}
</code>```

答:
Here is another approach for you. If you want to know which scholar is in which publication, you can do the following as well. First, assign unique IDs to publications. Then, split authors and create a long-format data frame. Define groups by authors and aggregate publication ID (pub_id) as string (character). If you need to extract some authors, you can use this data frame (foo) and subset rows.

```<code>library(tidyverse)

mutate(sampleDat, pub_id = 1:n()) %>%
separate_rows(var1, sep = ",\\s") %>%
group_by(var1) %>%
summarize(pub_id = toString(pub_id)) -> foo

  var1       pub_id
  <chr>      <chr>
1 Carst W    2
2 Cronauer R 2
3 Doe J      1
4 Hey B      3
5 Joff S     3
6 Kim HE     1
7 Maxwell M  1
8 Theobald U 2, 3

filter(foo, var1 %in% c("Doe J", "Theobald U"))

  var1       pub_id
  <chr>      <chr>
1 Doe J      1
2 Theobald U 2, 3
</code>```

If you want to have index as numeric, you can twist the idea above and do the following. You can subset rows with targeted names with filter().

```<code>mutate(sampleDat, pub_id = 1:n()) %>%
separate_rows(var1, sep = ",\\s") %>%
group_by(var1) %>%
summarize(pub_id = list(pub_id)) %>%
unnest(pub_id)

  var1       pub_id
  <chr>       <int>
1 Carst W         2
2 Cronauer R      2
3 Doe J           1
4 Hey B           3
5 Joff S          3
6 Kim HE          1
7 Maxwell M       1
8 Theobald U      2
9 Theobald U      3
</code>```

Body:
I work with a sheet of data that lists a variety of scientific publications. Rows are publications,
columns are a variety of metrics describing each publication (author name and position, Pubmed IDs, Date etc...)
I want to filter for publications for each author and extract parts of them. The caveat is the format:
all author names (5-80 per cell) are lumped together in one cell for each row.

I managed to solve this with the use of str_which, saving the coordinates for each author and later extract. This works only for manual use. When I try to automate this process using a loop to draw on a list of authors I fail to save the output.

I am at a bit of a loss on how to store the results without overwriting previous ones.

sampleDat <-
  data.frame(var1 = c("Doe J, Maxwell M, Kim HE", "Cronauer R, Carst W, Theobald U", "Theobald U, Hey B, Joff S"),
             var2 = c(1:3),
             var3 = c("2016-01", "2016-03", "2017-05"))

list of names that I want the coordinates for

namesOfInterest <-
  list(c("Doe J", "Theobald U"))

the manual extraction, requiring me to type the exact name and output object

Doe <- str_which(sampleDat$var1, "Doe J")
Theobald <- str_which(sampleDat$var1, "Theobald U")

one of many attempts that does not replicate the manual version.

results <- c()

for (i in namesOfInterest) {
  results[i] <- str_which(sampleDat$var1, i)
}

Body:
Here is another approach for you. If you want to know which scholar is in which publication, you can do the following as well. First, assign unique IDs to publications. Then, split authors and create a long-format data frame. Define groups by authors and aggregate publication ID (pub_id) as string (character). If you need to extract some authors, you can use this data frame (foo) and subset rows.

library(tidyverse)

mutate(sampleDat, pub_id = 1:n()) %>%
separate_rows(var1, sep = ",\\s") %>%
group_by(var1) %>%
summarize(pub_id = toString(pub_id)) -> foo

  var1       pub_id
  <chr>      <chr>
1 Carst W    2
2 Cronauer R 2
3 Doe J      1
4 Hey B      3
5 Joff S     3
6 Kim HE     1
7 Maxwell M  1
8 Theobald U 2, 3

filter(foo, var1 %in% c("Doe J", "Theobald U"))

  var1       pub_id
  <chr>      <chr>
1 Doe J      1
2 Theobald U 2, 3

If you want to have index as numeric, you can twist the idea above and do the following. You can subset rows with targeted names with filter().

mutate(sampleDat, pub_id = 1:n()) %>%
separate_rows(var1, sep = ",\\s") %>%
group_by(var1) %>%
summarize(pub_id = list(pub_id)) %>%
unnest(pub_id)

  var1       pub_id
  <chr>       <int>
1 Carst W         2
2 Cronauer R      2
3 Doe J           1
4 Hey B           3
5 Joff S          3
6 Kim HE          1
7 Maxwell M       1
8 Theobald U      2
9 Theobald U      3


问:
HTML Input Gradient Text
Been looking for a solution but no prevail, so I thought I'd ask here.

I am trying to apply a linear gradient to the input field as I have for the buttons as seen in this picture.

I have played around with different CSS options but have not been able to succeed.

The best version is where the placeholder is styled, but the input value is not. If I try to style the input value then things go wrong.

And advice would be greatly appreciated.

button{
  background-color: dodgerblue;
  height: 60px;
  width: 60px;
  border-radius: 50%;
  font-size: 32px
}

button i{
  background: -webkit-linear-gradient(#ffffff70, #ffffff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

input{
  background-color: dodgerblue;
  height: 60px;
  width: 360px;
  font-size: 32px
}

input::placeholder{
  background: -webkit-linear-gradient(#ffffff70, #ffffff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

/*
input:focus {
    background: -webkit-linear-gradient(#ffffff70, #ffffff);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
*/```
<pre class="snippet-code-html lang-html prettyprint-override"><code><button><i>X</i></button>

<hr />

<input placeholder="SEARCH"/></code>```

答:
if your trying to set a gradient on the placeholder text,
your best option is to omit or remove the placeholder completely and set another div over the top of the input with your chosen font, and the text gradient.

```<code><div id="InpCont">
   <input type="text" id="UsrInp">
   <div id="InpOverlay">
      <p id="PsudoPlcHlder" class="OverlayTxt" contenteditable="true" onchange="PsudoPlcHlder.value=UsrInp.value" max-length="44">Search</p>
   </div>
</div>
</code>```

```<code>#InpCont{
   // Position Where you want this element
   }
#UsrInp{
   position:absolute;
   top:8px; left:50%;
   transform:translateX(-50%);
   width:64%; height:calc(28px + 1.87vh);
   background:linear-gradient(-33deg,#ffffff70, #ffffff);
   z-index:20;
   }
#PsudoPlcHlder{
    position:relative;
    top:-40px; left:calc(20px + 25%);
    width:240px; height:29px; padding:2px;
    background:linear-gradient(23deg,red,green,blue);
    overflow-x:hidden;
    background-clip:text;
    color:transparent;
    z-index:25;
    }
</code>```

```<code>(document.addEventListener('DOMContentLoaded', function(){
    const UsrInp = document.getElementById('UsrInp');
    const PsudoPlcHlder = document.getElementById('PsudoPlcHlder');

    PsudoPlcHlder.addEventListener('click', (function(){
         PsudoPlcHlder.innerText = '';
    }))
})
</code>```

Just tried this on my own app and it seems to be working, but i'm not sure about the form submission part as I haven't got it hooked up to a db at the moment, might have to play around with the positioning a bit as I only tested this at the very bottom of my app, but might be a good starting point for you to mess around with.

in testing this, the gradient seems to stretch to fit, however many characters there are even if there like 120, which is a bit weird. will play around with this more and edit later on if I find any better methods..

Title: HTML Input Gradient Text

Body:
Been looking for a solution but no prevail, so I thought I'd ask here.

I am trying to apply a linear gradient to the input field as I have for the buttons as seen in this picture.

I have played around with different CSS options but have not been able to succeed.

The best version is where the placeholder is styled, but the input value is not. If I try to style the input value then things go wrong.

And advice would be greatly appreciated.

button{
  background-color: dodgerblue;
  height: 60px;
  width: 60px;
  border-radius: 50%;
  font-size: 32px
}

button i{
  background: -webkit-linear-gradient(#ffffff70, #ffffff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

input{
  background-color: dodgerblue;
  height: 60px;
  width: 360px;
  font-size: 32px
}

input::placeholder{
  background: -webkit-linear-gradient(#ffffff70, #ffffff);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

/*
input:focus {
    background: -webkit-linear-gradient(#ffffff70, #ffffff);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}
*/

<button>X</button>

<input placeholder="SEARCH"/>

Body:
if your trying to set a gradient on the placeholder text,
your best option is to omit or remove the placeholder completely and set another div over the top of the input with your chosen font, and the text gradient.

<div id="InpCont">
   <input type="text" id="UsrInp">
   <div id="InpOverlay">
      <p id="PsudoPlcHlder" class="OverlayTxt" contenteditable="true" onchange="PsudoPlcHlder.value=UsrInp.value" max-length="44">Search</p>
   </div>
</div>

#InpCont{
   // Position Where you want this element
   }
#UsrInp{
   position:absolute;
   top:8px; left:50%;
   transform:translateX(-50%);
   width:64%; height:calc(28px + 1.87vh);
   background:linear-gradient(-33deg,#ffffff70, #ffffff);
   z-index:20;
   }
#PsudoPlcHlder{
    position:relative;
    top:-40px; left:calc(20px + 25%);
    width:240px; height:29px; padding:2px;
    background:linear-gradient(23deg,red,green,blue);
    overflow-x:hidden;
    background-clip:text;
    color:transparent;
    z-index:25;
    }

(document.addEventListener('DOMContentLoaded', function(){
    const UsrInp = document.getElementById('UsrInp');
    const PsudoPlcHlder = document.getElementById('PsudoPlcHlder');

    PsudoPlcHlder.addEventListener('click', (function(){
         PsudoPlcHlder.innerText = '';
    }))
})

Just tried this on my own app and it seems to be working, but i'm not sure about the form submission part as I haven't got it hooked up to a db at the moment, might have to play around with the positioning a bit as I only tested this at the very bottom of my app, but might be a good starting point for you to mess around with.

in testing this, the gradient seems to stretch to fit, however many characters there are even if there like 120, which is a bit weird. will play around with this more and edit later on if I find any better methods..


问:
Multiple Sub Queries with Multiple JOINS Oracle
I have a large ORACLE SQL file with multi joins and multiple sub queries.  I am having issues joining two of the sub queries.  I have tried many different methods but the closest that I have gotten is below.  The piece that is giving me trouble is the first portion of the join with the multiple subqueries (the Address Eff Date and the Employee Eff Date.  The error message that I am receiving is ORA-00907: missing right parenthesis 00907. 00000 -  "missing right parenthesis".  I can't find where the right parenthesis is missing and I suspect it is more than that or some other type of syntax issue.  The two tables that I have had trouble joinging are the EMPLOYEE_EFF_DATE table and the ADDRESS_EFF_DATE table.  Both of these tables have an EFF_DATE field, and for both tables I need to pull the record with the most recent effective date (by SSN field).  I believe I have accounted for that with the ROW_NUMBER() OVER (PARTITION method but if there is a more efficient or easier way to to this I am absolutely open to suggestions.  </p>

```<code>/*Subscriber Code*/
    eed.P_COMPANY_ID_I as "Client Company ID"
    ,cs.REAL_SSN as "Employee SSN"
    ,cs.REAL_SSN as "Member SSN"
    ,'Subscriber' as "Person Type"
    ,eed.LAST_NAME as "Last Name"
    ,eed.FIRST_NAME as "First Name"
    ,eed.BIRTHDATE as "Date of Birth"
    ,eed.SEX as "Gender"
    ,aed.Address_1 as "Address 1"
    ,aed.Address_2 as "Address 2"
    ,aed.City
    ,aed.State
    ,aed.Zip
    ,aed.Country as "Country Code"
    ,aed.Telephone as "Employee Home Phone"
    ,eed.EMAIL_ADDRESS as "Employee Email Address"

    ,CASE
        WHEN eed.controlled_group_status = 'L'
        OR eed.controlled_group_status = 'P'
        then eed.EFF_DATE
        ELSE NULL
    END
    as "Date Last Actively At Work"
    /*Remove line below*/
    ,eed.CONTROLLED_GROUP_STATUS
    ,CASE
        WHEN eed.controlled_group_status = 'L'
        OR eed.controlled_group_status = 'P'
        then 'LEAVE'
        ELSE NULL
    END
    as "Leave Status"
    ,CASE
        WHEN eed.controlled_group_status = 'L'
        OR eed.controlled_group_status = 'P'
        then eed.EFF_DATE + 1
        ELSE NULL
    END
    as "Leave Begin Date"
    ,eed.LATEST_HIRE_DATE as "Employee Date of Hire"
    ,eed.LAST_TERM_DATE as "Employee Date of Termination"
    ,mcemd.RATE_1 as "Employee Salary"
    ,ele.LIFE_EVENT_ID as "Life Event ID"
    ,ele.LIFE_EVENT_DATE as "Loss of Coverage Date"

FROM

/*Employee_Eff_Date*/
(SELECT *
FROM
(SELECT *
FROM
     (SELECT eed1.*,
             ROW_NUMBER() OVER (PARTITION BY eed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM EMPLOYEE_EFF_DATE eed1)
WHERE seqnum = 1) eed)

JOIN
/*Address_Eff_Date*/
(SELECT *
FROM
    (SELECT *
    FROM
     (SELECT aed1.*,
             ROW_NUMBER() OVER (PARTITION BY aed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM ADDRESS_EFF_DATE aed1
     ) aed1
     ON aed1.SSN = eed.SSN
WHERE aed1.seqnum = 1) aed)

INNER JOIN COMPANY_EMPLOYMENT_DATA ced
    ON eed.SSN = ced.SSN
INNER JOIN MV_COMB_EMP_MAX_DTS mcemd
    ON eed.SSN = mcemd.SSN
INNER JOIN EMPLOYEE_LIFE_EVENTS ele
    ON ele.SSN = eed.SSN

WHERE eed.P_COMPANY_ID_I = 1234

/*Address_Eff_Date qualifying statement*/
AND aed.ADDRESS_KEY = 0

/*EMPLOYEE_LIFE_EVENTS qualifying statement*/
/*Below line indicates the Life Event Dates (set to the past week)*/
AND ele.LIFE_EVENT_DATE >= sysdate-7
AND ele.LIFE_EVENT_DATE <= sysdate
</code>```

答:
I think you actually want this. Note you have more level of query nesting than you actually need and I have removed the extra ones:</p>

```<code>/*Employee_Eff_Date*/
(SELECT *
FROM
     (SELECT eed1.*,
             ROW_NUMBER() OVER (PARTITION BY eed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM EMPLOYEE_EFF_DATE eed1) eed1
WHERE seqnum = 1) eed
JOIN
/*Address_Eff_Date*/
(SELECT *
 FROM
     (SELECT aed1.*,
             ROW_NUMBER() OVER (PARTITION BY aed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM ADDRESS_EFF_DATE aed1
     ) aed1
     WHERE aed1.seqnum = 1) aed ON aed.SSN = eed.SSN
</code>```

Body:
I have a large ORACLE SQL file with multi joins and multiple sub queries.  I am having issues joining two of the sub queries.  I have tried many different methods but the closest that I have gotten is below.  The piece that is giving me trouble is the first portion of the join with the multiple subqueries (the Address Eff Date and the Employee Eff Date.  The error message that I am receiving is ORA-00907: missing right parenthesis 00907. 00000 -  "missing right parenthesis".  I can't find where the right parenthesis is missing and I suspect it is more than that or some other type of syntax issue.  The two tables that I have had trouble joinging are the EMPLOYEE_EFF_DATE table and the ADDRESS_EFF_DATE table.  Both of these tables have an EFF_DATE field, and for both tables I need to pull the record with the most recent effective date (by SSN field).  I believe I have accounted for that with the ROW_NUMBER() OVER (PARTITION method but if there is a more efficient or easier way to to this I am absolutely open to suggestions.

/*Subscriber Code*/
    eed.P_COMPANY_ID_I as "Client Company ID"
    ,cs.REAL_SSN as "Employee SSN"
    ,cs.REAL_SSN as "Member SSN"
    ,'Subscriber' as "Person Type"
    ,eed.LAST_NAME as "Last Name"
    ,eed.FIRST_NAME as "First Name"
    ,eed.BIRTHDATE as "Date of Birth"
    ,eed.SEX as "Gender"
    ,aed.Address_1 as "Address 1"
    ,aed.Address_2 as "Address 2"
    ,aed.City
    ,aed.State
    ,aed.Zip
    ,aed.Country as "Country Code"
    ,aed.Telephone as "Employee Home Phone"
    ,eed.EMAIL_ADDRESS as "Employee Email Address"

    ,CASE
        WHEN eed.controlled_group_status = 'L'
        OR eed.controlled_group_status = 'P'
        then eed.EFF_DATE
        ELSE NULL
    END
    as "Date Last Actively At Work"
    /*Remove line below*/
    ,eed.CONTROLLED_GROUP_STATUS
    ,CASE
        WHEN eed.controlled_group_status = 'L'
        OR eed.controlled_group_status = 'P'
        then 'LEAVE'
        ELSE NULL
    END
    as "Leave Status"
    ,CASE
        WHEN eed.controlled_group_status = 'L'
        OR eed.controlled_group_status = 'P'
        then eed.EFF_DATE + 1
        ELSE NULL
    END
    as "Leave Begin Date"
    ,eed.LATEST_HIRE_DATE as "Employee Date of Hire"
    ,eed.LAST_TERM_DATE as "Employee Date of Termination"
    ,mcemd.RATE_1 as "Employee Salary"
    ,ele.LIFE_EVENT_ID as "Life Event ID"
    ,ele.LIFE_EVENT_DATE as "Loss of Coverage Date"

FROM

/*Employee_Eff_Date*/
(SELECT *
FROM
(SELECT *
FROM
     (SELECT eed1.*,
             ROW_NUMBER() OVER (PARTITION BY eed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM EMPLOYEE_EFF_DATE eed1)
WHERE seqnum = 1) eed)

JOIN
/*Address_Eff_Date*/
(SELECT *
FROM
    (SELECT *
    FROM
     (SELECT aed1.*,
             ROW_NUMBER() OVER (PARTITION BY aed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM ADDRESS_EFF_DATE aed1
     ) aed1
     ON aed1.SSN = eed.SSN
WHERE aed1.seqnum = 1) aed)

INNER JOIN COMPANY_EMPLOYMENT_DATA ced
    ON eed.SSN = ced.SSN
INNER JOIN MV_COMB_EMP_MAX_DTS mcemd
    ON eed.SSN = mcemd.SSN
INNER JOIN EMPLOYEE_LIFE_EVENTS ele
    ON ele.SSN = eed.SSN

WHERE eed.P_COMPANY_ID_I = 1234

/*Address_Eff_Date qualifying statement*/
AND aed.ADDRESS_KEY = 0

/*EMPLOYEE_LIFE_EVENTS qualifying statement*/
/*Below line indicates the Life Event Dates (set to the past week)*/
AND ele.LIFE_EVENT_DATE >= sysdate-7
AND ele.LIFE_EVENT_DATE <= sysdate

Body:
I think you actually want this. Note you have more level of query nesting than you actually need and I have removed the extra ones:

/*Employee_Eff_Date*/
(SELECT *
FROM
     (SELECT eed1.*,
             ROW_NUMBER() OVER (PARTITION BY eed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM EMPLOYEE_EFF_DATE eed1) eed1
WHERE seqnum = 1) eed
JOIN
/*Address_Eff_Date*/
(SELECT *
 FROM
     (SELECT aed1.*,
             ROW_NUMBER() OVER (PARTITION BY aed1.SSN ORDER BY EFF_DATE DESC) as seqnum
      FROM ADDRESS_EFF_DATE aed1
     ) aed1
     WHERE aed1.seqnum = 1) aed ON aed.SSN = eed.SSN


问:
How to access incremented values inside a loop in c
I'm new in programming and I'm stuck on code that reads the integer N from input and prints the first N integers of the following series:

```<code>1, -1, -2, 2, 3, -3, -4, 4, 5, -5, -6, 6, 7, -7, ...
</code>```

for example if the N is 4 it prints:

```<code>1, -1, -2, 2
</code>```

I wrote my code and it contains a while loop. I need the last value of t and i, which are incremented in the loop, outside of the loop but it doesn't work.

This is my code:

```<code>#include <stdio.h>

int main(void) {
    int n;
    printf("Enter your number: ");
    scanf("%d", &n);

    int i = 1;
    int t = 1;
    while (i <= (n / 2)) {
        int t = i;
        if (i % 2 == 0)
            t *= -1;

        printf("%d", t);
        printf(", %d, ", -t);
        i++;
    }
    if (n % 2 == 1) {
        printf("%d", -t / i * (n + 1) / 2);
    }
    return 0;
}
</code>```

Actually I need that outer part of the code for the odd N's (because when N is an even number like 4, numbers are paired like 1, -1, -2, 2 but when it's odd the last number is single like N=5,1, -1, -2, 2, 3 ). For even N's it works but for the odd's it prints 0 instead of  the last number of the series.

Sorry if my explanation is not clear but I would appreciate any help.

答:
You can see replay about the definition of internal variable k hidden outer one. I'd like to say about the code.

In my view, there are two cases in the code: the first, you increment number; the second, you invert the sign. Also, you print a number in both cases. So, I think, it can be implemented a little clearer:

```<code>#include <stdio.h>

int main() {

    int n;
    printf("enter number:\n");
    scanf("%d",&n);

    for (int i = 0, sign = 1, j = 1; i < n; ++i) {
        if (i > 0)
            printf(", ");

        printf("%d",j*sign);

        if (i%2 == 0)
            sign = -sign;
        if (i%2 == 1)
            ++j;
    }

    putchar('\n');
    return 0;
}
</code>```

Body:
I'm new in programming and I'm stuck on code that reads the integer N from input and prints the first N integers of the following series:

1, -1, -2, 2, 3, -3, -4, 4, 5, -5, -6, 6, 7, -7, ...

for example if the N is 4 it prints:

1, -1, -2, 2

I wrote my code and it contains a while loop. I need the last value of t and i, which are incremented in the loop, outside of the loop but it doesn't work.

This is my code:

#include <stdio.h>

int main(void) {
    int n;
    printf("Enter your number: ");
    scanf("%d", &n);

    int i = 1;
    int t = 1;
    while (i <= (n / 2)) {
        int t = i;
        if (i % 2 == 0)
            t *= -1;

        printf("%d", t);
        printf(", %d, ", -t);
        i++;
    }
    if (n % 2 == 1) {
        printf("%d", -t / i * (n + 1) / 2);
    }
    return 0;
}

Actually I need that outer part of the code for the odd N's (because when N is an even number like 4, numbers are paired like 1, -1, -2, 2 but when it's odd the last number is single like N=5,1, -1, -2, 2, 3 ). For even N's it works but for the odd's it prints 0 instead of  the last number of the series.

Sorry if my explanation is not clear but I would appreciate any help.

Body:
You can see replay about the definition of internal variable k hidden outer one. I'd like to say about the code.

In my view, there are two cases in the code: the first, you increment number; the second, you invert the sign. Also, you print a number in both cases. So, I think, it can be implemented a little clearer:

#include <stdio.h>

int main() {

    int n;
    printf("enter number:\n");
    scanf("%d",&n);

    for (int i = 0, sign = 1, j = 1; i < n; ++i) {
        if (i > 0)
            printf(", ");

        printf("%d",j*sign);

        if (i%2 == 0)
            sign = -sign;
        if (i%2 == 1)
            ++j;
    }

    putchar('\n');
    return 0;
}


Title: Manipulating Array of object in Javascript


问:
Largest Series Product

Given a string of digits, calculate the largest product for a contiguous substring of digits of length n.  For example, for the input '1027839564', the largest product for a series of 3 digits is 270 (9 * 5 * 6), and the largest product for a series of 5 digits is 7560 (7 * 8 * 3 * 9 * 5).  Note that these series are only required to occupy adjacent positions in the input; the digits need not be numerically consecutive.  For the input '73167176531330624919225119674426574742355349194934', the largest product for a series of 6 digits is 23520.>

I am trying to complete a code challenge from exercism.io  That is the description given.  I am on my second refactor yet I am still failing on two test cases.

```<code>using System;
using System.Collections.Generic;
using System.Linq;

public static class LargestSeriesProduct
{
    /* Function to get product of digits */
    static int getProduct(int n)
    {
        int product = 1;

        while (n != 0)
        {
            product = product * (n % 10);
            n = n / 10;
        }

        return product;
    }

    static long getAnswer(string d, int s)
    {
        List<string> listString = new List<string>();

        for (int i = 0; i < d.Length - s + 1; ++i)
            listString.Add(d.Substring(i, s));

        List<int> listInt = listString.ConvertAll(int.Parse);

        return getProduct(listInt.Max());
    }

    public static long GetLargestProduct(string digits, int span)
    {
        if (span > digits.Length)
        {
            throw new ArgumentException("Rejects_span_longer_than_string_length");
        }

        else if (span == 0 || digits.Length == 0)
        {
            return 1;
        }

        else if (span == 1 && digits.Length == 0)
        {
            throw new ArgumentException("Rejects_empty_string_and_nonzero_span");
        }

        else if (span < 0)
        {
            throw new ArgumentException("Rejects_negative_span");
        }

        else if (!digits.All(char.IsDigit))
        {
            throw new ArgumentException("Rejects_invalid_character_in_digits");
        }

        else if (digits.All(c => c == '0'))
        {
            return 0;
        }

        else
        {
            return getAnswer(digits, span);
        }
    }
}

/*
public static class LargestSeriesProduct
{
    public static long GetLargestProduct(string digits, int span)
    {
        try
        {
            return Enumerable.Range(0, digits.Length - span + 1).
            Select(i => digits.Substring(i, span)).
            Select(x => x.Aggregate(1, (a, b) => a * Convert.ToInt32(b.ToString()))).
            Max();
        }
        catch
        {
            throw new ArgumentException();
        }
    }
}
*/
</code>```

The code that is commented out is the most popular answer.  However, that is not my answer an I am trying to figure this out on my own.  I walked through the code one test at a time.  I am stuck on two test cases.  The following two cases have skip enabled on the test

```<code>// This file was auto-generated based on version 1.2.0 of the canonical data.

using System;
using Xunit;

public class LargestSeriesProductTest
{
    [Fact]
    public void Finds_the_largest_product_if_span_equals_length() => Assert.Equal(18, LargestSeriesProduct.GetLargestProduct("29", 2));

    [Fact]
    public void Can_find_the_largest_product_of_2_with_numbers_in_order() => Assert.Equal(72, LargestSeriesProduct.GetLargestProduct("0123456789", 2));

    [Fact(Skip = "specific reason")]
    public void Can_find_the_largest_product_of_2() => Assert.Equal(48, LargestSeriesProduct.GetLargestProduct("576802143", 2));

    [Fact]
    public void Can_find_the_largest_product_of_3_with_numbers_in_order() => Assert.Equal(504, LargestSeriesProduct.GetLargestProduct("0123456789", 3));

    [Fact]
    public void Can_find_the_largest_product_of_3() => Assert.Equal(270, LargestSeriesProduct.GetLargestProduct("1027839564", 3));

    [Fact]
    public void Can_find_the_largest_product_of_5_with_numbers_in_order() => Assert.Equal(15120, LargestSeriesProduct.GetLargestProduct("0123456789", 5));

    [Fact(Skip = "specific reason")]
    public void Can_get_the_largest_product_of_a_big_number() => Assert.Equal(23520, LargestSeriesProduct.GetLargestProduct("73167176531330624919225119674426574742355349194934", 6));

    [Fact]
    public void Reports_zero_if_the_only_digits_are_zero() => Assert.Equal(0, LargestSeriesProduct.GetLargestProduct("0000", 2));

    [Fact]
    public void Reports_zero_if_all_spans_include_zero() => Assert.Equal(0, LargestSeriesProduct.GetLargestProduct("99099", 3));

    [Fact]
    public void Rejects_span_longer_than_string_length() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("123", 4));

    [Fact]
    public void Reports_1_for_empty_string_and_empty_product_0_span_() => Assert.Equal(1, LargestSeriesProduct.GetLargestProduct("", 0));

    [Fact]
    public void Reports_1_for_nonempty_string_and_empty_product_0_span_() => Assert.Equal(1, LargestSeriesProduct.GetLargestProduct("123", 0));

    [Fact]
    public void Rejects_empty_string_and_nonzero_span() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("", 1));

    [Fact]
    public void Rejects_invalid_character_in_digits() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("1234a5", 2));

    [Fact]
    public void Rejects_negative_span() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("12345", -1));
}
</code>```

I have tried regex to remove the 0's, but that causes other passing test to fail.  I have tried changing 0's to 1's, but that creates a different product.  The best clue I can give to pass all these test are in the commented out code below my own.  I am trying to work with what I got, complete it, and then go and refactor it into something less verbose with the knowledge I have with C#.  I am new to C#.

Any help with passing those two test without failing the other test I have passed is much appreciated.

答:
I see what Michael Randall was saying now.  This was the code suggested in that link.  It passes all test.  I'm just going to accept this and disregard my code as being unacceptable to refactor.  This is more concise and readable as well.</p>

```<code>using System;
using System.Linq;
using System.Numerics;

public static class LargestSeriesProduct
{
    static BigInteger getAnswer(string d, int s) => Enumerable.Range(0, d.Length - s + 1)
        .Select(i => d.Substring(i, s))
        .Select(n => n.Aggregate(new BigInteger(1), (current, t) => current * (t - '0')))
        .OrderByDescending(x => x)
        .First();

    public static long GetLargestProduct(string digits, int span)
    {
        if (span > digits.Length)
        {
            throw new ArgumentException("Rejects_span_longer_than_string_length");
        }

        else if (span == 0 || digits.Length == 0)
        {
            return 1;
        }

        else if (span == 1 && digits.Length == 0)
        {
            throw new ArgumentException("Rejects_empty_string_and_nonzero_span");
        }

        else if (span < 0)
        {
            throw new ArgumentException("Rejects_negative_span");
        }

        else if (!digits.All(char.IsDigit))
        {
            throw new ArgumentException("Rejects_invalid_character_in_digits");
        }

        else if (digits.All(c => c == '0'))
        {
            return 0;
        }

        else
        {
            return (int)getAnswer(digits, span);
        }
    }
}
</code>```

Title: Largest Series Product

Body:
Given a string of digits, calculate the largest product for a contiguous substring of digits of length n.  For example, for the input '1027839564', the largest product for a series of 3 digits is 270 (9 * 5 * 6), and the largest product for a series of 5 digits is 7560 (7 * 8 * 3 * 9 * 5).  Note that these series are only required to occupy adjacent positions in the input; the digits need not be numerically consecutive.  For the input '73167176531330624919225119674426574742355349194934', the largest product for a series of 6 digits is 23520.>

I am trying to complete a code challenge from exercism.io  That is the description given.  I am on my second refactor yet I am still failing on two test cases.

using System;
using System.Collections.Generic;
using System.Linq;

public static class LargestSeriesProduct
{
    /* Function to get product of digits */
    static int getProduct(int n)
    {
        int product = 1;

        while (n != 0)
        {
            product = product * (n % 10);
            n = n / 10;
        }

        return product;
    }

    static long getAnswer(string d, int s)
    {
        List<string> listString = new List<string>();

        for (int i = 0; i < d.Length - s + 1; ++i)
            listString.Add(d.Substring(i, s));

        List<int> listInt = listString.ConvertAll(int.Parse);

        return getProduct(listInt.Max());
    }

    public static long GetLargestProduct(string digits, int span)
    {
        if (span > digits.Length)
        {
            throw new ArgumentException("Rejects_span_longer_than_string_length");
        }

        else if (span == 0 || digits.Length == 0)
        {
            return 1;
        }

        else if (span == 1 && digits.Length == 0)
        {
            throw new ArgumentException("Rejects_empty_string_and_nonzero_span");
        }

        else if (span < 0)
        {
            throw new ArgumentException("Rejects_negative_span");
        }

        else if (!digits.All(char.IsDigit))
        {
            throw new ArgumentException("Rejects_invalid_character_in_digits");
        }

        else if (digits.All(c => c == '0'))
        {
            return 0;
        }

        else
        {
            return getAnswer(digits, span);
        }
    }
}

/*
public static class LargestSeriesProduct
{
    public static long GetLargestProduct(string digits, int span)
    {
        try
        {
            return Enumerable.Range(0, digits.Length - span + 1).
            Select(i => digits.Substring(i, span)).
            Select(x => x.Aggregate(1, (a, b) => a * Convert.ToInt32(b.ToString()))).
            Max();
        }
        catch
        {
            throw new ArgumentException();
        }
    }
}
*/

The code that is commented out is the most popular answer.  However, that is not my answer an I am trying to figure this out on my own.  I walked through the code one test at a time.  I am stuck on two test cases.  The following two cases have skip enabled on the test

// This file was auto-generated based on version 1.2.0 of the canonical data.

using System;
using Xunit;

public class LargestSeriesProductTest
{
    [Fact]
    public void Finds_the_largest_product_if_span_equals_length() => Assert.Equal(18, LargestSeriesProduct.GetLargestProduct("29", 2));

    [Fact]
    public void Can_find_the_largest_product_of_2_with_numbers_in_order() => Assert.Equal(72, LargestSeriesProduct.GetLargestProduct("0123456789", 2));

    [Fact(Skip = "specific reason")]
    public void Can_find_the_largest_product_of_2() => Assert.Equal(48, LargestSeriesProduct.GetLargestProduct("576802143", 2));

    [Fact]
    public void Can_find_the_largest_product_of_3_with_numbers_in_order() => Assert.Equal(504, LargestSeriesProduct.GetLargestProduct("0123456789", 3));

    [Fact]
    public void Can_find_the_largest_product_of_3() => Assert.Equal(270, LargestSeriesProduct.GetLargestProduct("1027839564", 3));

    [Fact]
    public void Can_find_the_largest_product_of_5_with_numbers_in_order() => Assert.Equal(15120, LargestSeriesProduct.GetLargestProduct("0123456789", 5));

    [Fact(Skip = "specific reason")]
    public void Can_get_the_largest_product_of_a_big_number() => Assert.Equal(23520, LargestSeriesProduct.GetLargestProduct("73167176531330624919225119674426574742355349194934", 6));

    [Fact]
    public void Reports_zero_if_the_only_digits_are_zero() => Assert.Equal(0, LargestSeriesProduct.GetLargestProduct("0000", 2));

    [Fact]
    public void Reports_zero_if_all_spans_include_zero() => Assert.Equal(0, LargestSeriesProduct.GetLargestProduct("99099", 3));

    [Fact]
    public void Rejects_span_longer_than_string_length() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("123", 4));

    [Fact]
    public void Reports_1_for_empty_string_and_empty_product_0_span_() => Assert.Equal(1, LargestSeriesProduct.GetLargestProduct("", 0));

    [Fact]
    public void Reports_1_for_nonempty_string_and_empty_product_0_span_() => Assert.Equal(1, LargestSeriesProduct.GetLargestProduct("123", 0));

    [Fact]
    public void Rejects_empty_string_and_nonzero_span() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("", 1));

    [Fact]
    public void Rejects_invalid_character_in_digits() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("1234a5", 2));

    [Fact]
    public void Rejects_negative_span() => Assert.Throws<ArgumentException>(() => LargestSeriesProduct.GetLargestProduct("12345", -1));
}

I have tried regex to remove the 0's, but that causes other passing test to fail.  I have tried changing 0's to 1's, but that creates a different product.  The best clue I can give to pass all these test are in the commented out code below my own.  I am trying to work with what I got, complete it, and then go and refactor it into something less verbose with the knowledge I have with C#.  I am new to C#.

Any help with passing those two test without failing the other test I have passed is much appreciated.

Body:
I see what Michael Randall was saying now.  This was the code suggested in that link.  It passes all test.  I'm just going to accept this and disregard my code as being unacceptable to refactor.  This is more concise and readable as well.

using System;
using System.Linq;
using System.Numerics;

public static class LargestSeriesProduct
{
    static BigInteger getAnswer(string d, int s) => Enumerable.Range(0, d.Length - s + 1)
        .Select(i => d.Substring(i, s))
        .Select(n => n.Aggregate(new BigInteger(1), (current, t) => current * (t - '0')))
        .OrderByDescending(x => x)
        .First();

    public static long GetLargestProduct(string digits, int span)
    {
        if (span > digits.Length)
        {
            throw new ArgumentException("Rejects_span_longer_than_string_length");
        }

        else if (span == 0 || digits.Length == 0)
        {
            return 1;
        }

        else if (span == 1 && digits.Length == 0)
        {
            throw new ArgumentException("Rejects_empty_string_and_nonzero_span");
        }

        else if (span < 0)
        {
            throw new ArgumentException("Rejects_negative_span");
        }

        else if (!digits.All(char.IsDigit))
        {
            throw new ArgumentException("Rejects_invalid_character_in_digits");
        }

        else if (digits.All(c => c == '0'))
        {
            return 0;
        }

        else
        {
            return (int)getAnswer(digits, span);
        }
    }
}