问:
Dynamic SQL via jOOQ for paginating joined tables with same-named columns
I'm following a jOOQ blog post about paging metadata, and trying to implement it generally for a project. It demonstrates how to generically take an existing Select<?> and wrap it up to contain information about the current page, and how many other pages exist:

public static Select<?> paginate(
    DSLContext ctx,
    Select<?> original,
    Field<?>[] sort,
    int limit,
    int offset ) {
    Table<?> u = original.asTable("u");
    Field<Integer> totalRows = count().over().as("total_rows");
    Field<Integer> row = rowNumber().over().orderBy(u.fields(sort))
        .as("row");

    Table<?> t = ctx
        .select(u.asterisk())
        .select(totalRows, row)
        .from(u)
        .orderBy(u.fields(sort))
        .limit(limit)
        .offset(offset)
        .asTable("t");

    Select<?> result = ctx
        .select(t.fields(original.getSelect().toArray(Field[]::new)))
        .select(
            count().over().as("actual_page_size"),
            field(max(t.field(row)).over().eq(t.field(totalRows)))
                .as("last_page"),
            t.field(totalRows),
            t.field(row),
            t.field(row).minus(inline(1)).div(limit).plus(inline(1))
                .as("current_page"))
        .from(t)
        .orderBy(t.fields(sort));

    // System.out.println(result);
    return result;
}
```
<p>And here’s how you call the utility:</p>
```java System.out.println(
    paginate(
        ctx,
        ctx.select(ACTOR.ACTOR_ID, ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
           .from(ACTOR),
        new Field[] { ACTOR.ACTOR_ID },
        15,
        30
    ).fetch() );
```
<p>Notice that you can plug in arbitrary SQL fragments into that utility and paginate them. Irrespective of the complexity (including joins, other window functions, grouping, recursion, and what not), jOOQ will have you covered and will now paginate things for you.</p>
</blockquote>
<p>This works nicely for simple cases, but I am finding that it fails in any case where two columns happen to have the same name across joins - normally, the <code>record.into(FooRecord.class)</code> and <code>record.into(BarRecord.class)</code> would extract those columns and make them separately available to the caller.</p>
<p>For example, given two tables, <code>foo</code> and <code>bar</code>, where both have an <code>id</code> column, and <code>bar</code> has a <code>foo_id</code> foreign key. Then, I can write:</p>
<pre class="lang-java prettyprint-override"><code>var select = ctx
   .select(FOO.fields())
   .select(BAR.fields())
   .from(BAR)
   .leftJoin(FOO).on(BAR.FOO_ID.eq(FOO.ID));

// Render the SQL
System.out.println(select);
var data = select.fetch();

// Show the full query's results, then the fields that came from FOO and BAR
System.out.println(data);
System.out.println(data.get(2).into(FOO));
System.out.println(data.get(2).into(BAR));
</code>```

Results:

```<code>select "myschema"."foo"."id", "myschema"."bar"."id", "myschema"."bar"."foo_id"
from "myschema"."bar"
  left outer join "myschema"."foo"
    on "myschema"."bar"."foo_id" = "myschema"."foo"."id"
+----+----+------+
|  id|  id|foo_id|
+----+----+------+
|   1|   1|     1|
|   2|   2|     2|
|   2|   3|     2|
+----+----+------+

+----+
|  id|
+----+
|   2|
+----+

+----+------+
|  id|foo_id|
+----+------+
|   3|     2|
+----+------+
</code>```

Both jOOQ and the database (Postgres in this case) are happy with this, despite having more than one column with the same name.

Next, I try to pass this Select<?> to the paginate() method above:

```<code>var pagedSelect = paginate(ctx, original, new Field[] { FOO.ID }, 10, 0);

System.out.println(pagedSelect);
var pagedData = pagedSelect.fetch();//error
</code>```
```<code>select
  "t"."id",
  "t"."id",
  "t"."foo_id",
  count(*) over () as "actual_page_size",
  (max("t"."row") over () = "t"."total_rows") as "last_page",
  "t"."total_rows",
  "t"."row",
  ((("t"."row" - 1) / 10) + 1) as "current_page"
from (
  select
    "u".*,
    count(*) over () as "total_rows",
    row_number() over (order by "u"."id") as "row"
  from (
    select "myschema"."foo"."id", "myschema"."bar"."id", "myschema"."bar"."foo_id"
    from "myschema"."bar"
      left outer join "myschema"."foo"
        on "myschema"."bar"."foo_id" = "myschema"."foo"."id"
  ) as "u"
  order by "u"."id"
  offset 0 rows
  fetch next 10 rows only
) as "t"
order by "t"."id"

</code>```
```<code>ERROR: column referenced "id" is ambiguous
</code>```

My naive approach was to first try to modify paginate(...) to make the outer-most SELECT reference the fully qualified fields, table and all, but since we're querying from an anonymous table, that doesn't work, same error (though for a different reason, since now jOOQ is generating an alias for original.

Next I considered trying to visit original and create a copy of it, using AS to rename columns as f1, f2, f3, but I couldn't find a straightforward way to do this rewrite. Even if this had worked, it would make it hard to map them back again from the caller, which would need to then know the order of all the .select()ed fields to be able to find them again - and since the original might have itself been built from other dynamic SQL operations, that might not be feasible.

Finally I considered an approach where every column of every table was already qualified with the table name already, but beyond this being onerous, it also doesn't help at all in cases where a table could be joined twice into the same query.

What's the correct dynamic SQL approach with jOOQ to make it possible to wrap a query with pagination, and still map records back to their individual tables?

--

EDIT: Based on the comments, I've modified the query from the blog post, and while this actually emits runnable SQL, the premise of the blog post still seems faulty, and still eludes me.

Irrespective of the complexity (including joins, other window functions, grouping, recursion, and what not), jOOQ will have you covered and will now paginate things for you.

In this iteration, the as syntax for the nested selects now come with renamed columns, and the outer query uses those column names. In an attempt to still permit Record.into(Table) to work, it maps back again to the original columns, in order:

  public static Select<?> paginate(
          DSLContext ctx,
          Select<?> original,
          Field<?>[] sort,
          int limit,
          int offset ) {
    Map<List<String>, String> aliases = new LinkedHashMap<>();
    List<Field<?>> reverseAlias = new ArrayList<>();

    List<Field<?>> select = original.getSelect();
    for (int i = 0; i < select.size(); i++) {
      Field<?> field = select.get(i);
      aliases.put(Arrays.asList(field.getQualifiedName().getName()), "c" + i);
    }

    Table<?> u = original.asTable("u", aliases.values().toArray(String[]::new));
    Field<Integer> totalRows = count().over().as("total_rows");
    String[] sortFieldNames = Arrays.stream(sort).map(o -> aliases.get(Arrays.asList(o.getQualifiedName().getName()))).toArray(String[]::new);
    Field<Integer> row = rowNumber().over().orderBy(u.fields(sortFieldNames))
            .as("row");

    Table<?> t = ctx.select(u.asterisk())
            .select(totalRows, row)
            .from(u)
            .orderBy(u.fields(sortFieldNames))
            .limit(limit)
            .offset(offset)
            .asTable("t");

    for (int i = 0; i < select.size(); i++) {
      Field<?> field = select.get(i);
      reverseAlias.add(t.field("c" + i).as(field.getName()));
    }

    Select<?> result = ctx
            .select(reverseAlias)
            .select(
                    count().over().as("actual_page_size"),
                    field(max(t.field(row)).over().eq(t.field(totalRows)))
                            .as("last_page"),
                    t.field(totalRows),
                    t.field(row),
                    t.field(row).minus(inline(1)).div(limit).plus(inline(1))
                            .as("current_page"))
            .from(t)
            .orderBy(t.fields(sortFieldNames));

    return result;
  }
```
<p>This generates the following SQL:</p>
<pre class="lang-sql prettyprint-override"><code>select
  "t"."c1" as "id",
  "t"."c2" as "id",
  "t"."c3" as "foo_id",
  count(*) over () as "actual_page_size",
  (max("t"."row") over () = "t"."total_rows") as "last_page",
  "t"."total_rows",
  "t"."row",
  ((("t"."row" - 1) / 10) + 1) as "current_page"
from (
  select
    "u".*,
    count(*) over () as "total_rows",
    row_number() over (order by "u"."c1") as "row"
  from (
    select "myschema"."foo"."id", "myschema"."bar"."id", "myschema"."bar"."foo_id"
    from "myschema"."bar"
      left outer join "myschema"."foo"
        on "myschema"."bar"."foo_id" = "myschema"."foo"."id"
  ) as "u" ("c1", "c2", "c3")
  order by "u"."c1"
  offset 0 rows
  fetch next 10 rows only
) as "t"
order by "t"."c1"
</code>```

Note that as in the initial result sets, the first two columns are still labeled as id. However, Record.into(Table) no longer has the context it needs to understand that the first id column is for the foo table, and the second is for the bar table:

```<code>+----+----+------+----------------+---------+----------+----+------------+
|  id|  id|foo_id|actual_page_size|last_page|total_rows| row|current_page|
+----+----+------+----------------+---------+----------+----+------------+
|   1|   1|     1|               3|true     |         3|   1|           1|
|   2|   2|     2|               3|true     |         3|   2|           1|
|   2|   3|     2|               3|true     |         3|   3|           1|
+----+----+------+----------------+---------+----------+----+------------+

+----+
|  id|
+----+
|   2|
+----+

+----+------+
|  id|foo_id|
+----+------+
|   2|     2|
+----+------+
</code>```

So, to put the question in concrete terms: Is there a way to indicate to jOOQ that a Select<?>'s fields should be mapped to a particular Table?

And, as a more general question, but less subject to the X/Y problem: How can this paginate() method actually be used as in the example, with joins, where the joined tables have colliding column names? Is there a problem with this strategy of building up a query dynamically, and is there another strategy that can be followed instead, without this shortcoming?

Body:
I'm following a jOOQ blog post about paging metadata, and trying to implement it generally for a project. It demonstrates how to generically take an existing Select<?> and wrap it up to contain information about the current page, and how many other pages exist:

public static Select<?> paginate(
    DSLContext ctx,
    Select<?> original,
    Field<?>[] sort,
    int limit,
    int offset ) {
    Table<?> u = original.asTable("u");
    Field<Integer> totalRows = count().over().as("total_rows");
    Field<Integer> row = rowNumber().over().orderBy(u.fields(sort))
        .as("row");

    Table<?> t = ctx
        .select(u.asterisk())
        .select(totalRows, row)
        .from(u)
        .orderBy(u.fields(sort))
        .limit(limit)
        .offset(offset)
        .asTable("t");

    Select<?> result = ctx
        .select(t.fields(original.getSelect().toArray(Field[]::new)))
        .select(
            count().over().as("actual_page_size"),
            field(max(t.field(row)).over().eq(t.field(totalRows)))
                .as("last_page"),
            t.field(totalRows),
            t.field(row),
            t.field(row).minus(inline(1)).div(limit).plus(inline(1))
                .as("current_page"))
        .from(t)
        .orderBy(t.fields(sort));

    // System.out.println(result);
    return result;
}

And here’s how you call the utility:

java System.out.println(
    paginate(
        ctx,
        ctx.select(ACTOR.ACTOR_ID, ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
           .from(ACTOR),
        new Field[] { ACTOR.ACTOR_ID },
        15,
        30
    ).fetch() );

Notice that you can plug in arbitrary SQL fragments into that utility and paginate them. Irrespective of the complexity (including joins, other window functions, grouping, recursion, and what not), jOOQ will have you covered and will now paginate things for you.

This works nicely for simple cases, but I am finding that it fails in any case where two columns happen to have the same name across joins - normally, the record.into(FooRecord.class) and record.into(BarRecord.class) would extract those columns and make them separately available to the caller.

For example, given two tables, foo and bar, where both have an id column, and bar has a foo_id foreign key. Then, I can write:

var select = ctx
   .select(FOO.fields())
   .select(BAR.fields())
   .from(BAR)
   .leftJoin(FOO).on(BAR.FOO_ID.eq(FOO.ID));

// Render the SQL
System.out.println(select);
var data = select.fetch();

// Show the full query's results, then the fields that came from FOO and BAR
System.out.println(data);
System.out.println(data.get(2).into(FOO));
System.out.println(data.get(2).into(BAR));

Results:

select "myschema"."foo"."id", "myschema"."bar"."id", "myschema"."bar"."foo_id"
from "myschema"."bar"
  left outer join "myschema"."foo"
    on "myschema"."bar"."foo_id" = "myschema"."foo"."id"
+----+----+------+
|  id|  id|foo_id|
+----+----+------+
|   1|   1|     1|
|   2|   2|     2|
|   2|   3|     2|
+----+----+------+

+----+
|  id|
+----+
|   2|
+----+

+----+------+
|  id|foo_id|
+----+------+
|   3|     2|
+----+------+

Both jOOQ and the database (Postgres in this case) are happy with this, despite having more than one column with the same name.

Next, I try to pass this Select<?> to the paginate() method above:

var pagedSelect = paginate(ctx, original, new Field[] { FOO.ID }, 10, 0);

System.out.println(pagedSelect);
var pagedData = pagedSelect.fetch();//error

select
  "t"."id",
  "t"."id",
  "t"."foo_id",
  count(*) over () as "actual_page_size",
  (max("t"."row") over () = "t"."total_rows") as "last_page",
  "t"."total_rows",
  "t"."row",
  ((("t"."row" - 1) / 10) + 1) as "current_page"
from (
  select
    "u".*,
    count(*) over () as "total_rows",
    row_number() over (order by "u"."id") as "row"
  from (
    select "myschema"."foo"."id", "myschema"."bar"."id", "myschema"."bar"."foo_id"
    from "myschema"."bar"
      left outer join "myschema"."foo"
        on "myschema"."bar"."foo_id" = "myschema"."foo"."id"
  ) as "u"
  order by "u"."id"
  offset 0 rows
  fetch next 10 rows only
) as "t"
order by "t"."id"

ERROR: column referenced "id" is ambiguous

My naive approach was to first try to modify paginate(...) to make the outer-most SELECT reference the fully qualified fields, table and all, but since we're querying from an anonymous table, that doesn't work, same error (though for a different reason, since now jOOQ is generating an alias for original.

Next I considered trying to visit original and create a copy of it, using AS to rename columns as f1, f2, f3, but I couldn't find a straightforward way to do this rewrite. Even if this had worked, it would make it hard to map them back again from the caller, which would need to then know the order of all the .select()ed fields to be able to find them again - and since the original might have itself been built from other dynamic SQL operations, that might not be feasible.

Finally I considered an approach where every column of every table was already qualified with the table name already, but beyond this being onerous, it also doesn't help at all in cases where a table could be joined twice into the same query.

What's the correct dynamic SQL approach with jOOQ to make it possible to wrap a query with pagination, and still map records back to their individual tables?

--

EDIT: Based on the comments, I've modified the query from the blog post, and while this actually emits runnable SQL, the premise of the blog post still seems faulty, and still eludes me.

Irrespective of the complexity (including joins, other window functions, grouping, recursion, and what not), jOOQ will have you covered and will now paginate things for you.

In this iteration, the as syntax for the nested selects now come with renamed columns, and the outer query uses those column names. In an attempt to still permit Record.into(Table) to work, it maps back again to the original columns, in order:

  public static Select<?> paginate(
          DSLContext ctx,
          Select<?> original,
          Field<?>[] sort,
          int limit,
          int offset ) {
    Map<List<String>, String> aliases = new LinkedHashMap<>();
    List<Field<?>> reverseAlias = new ArrayList<>();

    List<Field<?>> select = original.getSelect();
    for (int i = 0; i < select.size(); i++) {
      Field<?> field = select.get(i);
      aliases.put(Arrays.asList(field.getQualifiedName().getName()), "c" + i);
    }

    Table<?> u = original.asTable("u", aliases.values().toArray(String[]::new));
    Field<Integer> totalRows = count().over().as("total_rows");
    String[] sortFieldNames = Arrays.stream(sort).map(o -> aliases.get(Arrays.asList(o.getQualifiedName().getName()))).toArray(String[]::new);
    Field<Integer> row = rowNumber().over().orderBy(u.fields(sortFieldNames))
            .as("row");

    Table<?> t = ctx.select(u.asterisk())
            .select(totalRows, row)
            .from(u)
            .orderBy(u.fields(sortFieldNames))
            .limit(limit)
            .offset(offset)
            .asTable("t");

    for (int i = 0; i < select.size(); i++) {
      Field<?> field = select.get(i);
      reverseAlias.add(t.field("c" + i).as(field.getName()));
    }

    Select<?> result = ctx
            .select(reverseAlias)
            .select(
                    count().over().as("actual_page_size"),
                    field(max(t.field(row)).over().eq(t.field(totalRows)))
                            .as("last_page"),
                    t.field(totalRows),
                    t.field(row),
                    t.field(row).minus(inline(1)).div(limit).plus(inline(1))
                            .as("current_page"))
            .from(t)
            .orderBy(t.fields(sortFieldNames));

    return result;
  }

This generates the following SQL:

select
  "t"."c1" as "id",
  "t"."c2" as "id",
  "t"."c3" as "foo_id",
  count(*) over () as "actual_page_size",
  (max("t"."row") over () = "t"."total_rows") as "last_page",
  "t"."total_rows",
  "t"."row",
  ((("t"."row" - 1) / 10) + 1) as "current_page"
from (
  select
    "u".*,
    count(*) over () as "total_rows",
    row_number() over (order by "u"."c1") as "row"
  from (
    select "myschema"."foo"."id", "myschema"."bar"."id", "myschema"."bar"."foo_id"
    from "myschema"."bar"
      left outer join "myschema"."foo"
        on "myschema"."bar"."foo_id" = "myschema"."foo"."id"
  ) as "u" ("c1", "c2", "c3")
  order by "u"."c1"
  offset 0 rows
  fetch next 10 rows only
) as "t"
order by "t"."c1"

Note that as in the initial result sets, the first two columns are still labeled as id. However, Record.into(Table) no longer has the context it needs to understand that the first id column is for the foo table, and the second is for the bar table:

+----+----+------+----------------+---------+----------+----+------------+
|  id|  id|foo_id|actual_page_size|last_page|total_rows| row|current_page|
+----+----+------+----------------+---------+----------+----+------------+
|   1|   1|     1|               3|true     |         3|   1|           1|
|   2|   2|     2|               3|true     |         3|   2|           1|
|   2|   3|     2|               3|true     |         3|   3|           1|
+----+----+------+----------------+---------+----------+----+------------+

+----+
|  id|
+----+
|   2|
+----+

+----+------+
|  id|foo_id|
+----+------+
|   2|     2|
+----+------+

So, to put the question in concrete terms: Is there a way to indicate to jOOQ that a Select<?>'s fields should be mapped to a particular Table?

And, as a more general question, but less subject to the X/Y problem: How can this paginate() method actually be used as in the example, with joins, where the joined tables have colliding column names? Is there a problem with this strategy of building up a query dynamically, and is there another strategy that can be followed instead, without this shortcoming?


来源: stackexchange

问:
How to parse JSON in groovy (jenkins) to read a specific value
i got stuck on splitting the values in json. I want to split the values for the key: ServerIPList. Here's the JSON format:

```<code>{
    ServerIPList : [
                      <PrivateIP>            <HOSTNAME>           <REGION>  <AWS ACCOUNT>
                    { 172.00.00.00 ,ip-172-00-00-00.ec2.internal ,us-east-1,123456789123 } ,
                   ] ,
    Operation : start,
    SNowTicket : RITM00001

}
</code>```

Here's my code:

```<code>import groovy.json.*
def message
pipeline {
  agent any
  options {
    buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5')
  }
  stages {
       stage('Recieve SQS Message') { steps {
       script {
            def aws = new AwsUtil()
            def success = aws.receiveSqsMessages(env.AWS_SQS_QUEUE, 1, { json ->
                message = new Util().jsonSlurper(json.Body)
                println message
                println message.ServerIPList
                println message.Operation
            result = sh (
                    script: "python ec2InstanceState.py ${message.ServerIPList} ${message.Operation}",
                    returnStdout: true
                ).trim()
</code>```

output of my code:

```<code>Body:{
    "ServerIPList" : "172.24.8.73","ip-172-00-00-00.ec2.internal","us-east-1","123456789123"
    "Operation" : "start",
    "SNowTicket" : "RITM1062357"
},
"172.24.8.73","ip-172-00-00-00.ec2.internal","us-east-1","123456789123"
"start"
"python ec2InstanceState.py "172.24.8.73","ip-172-00-00-00.ec2.internal","us-east-1","123456789123" start,
</code>```

Now, here i would like to grep only PrivateIp from the key: "ServerIPList". How to get it:

```<code>python ec2InstanceState.py 172.24.8.73 start
</code>```

ContentLicense: CC BY-SA 4.0

Body:
i got stuck on splitting the values in json. I want to split the values for the key: ServerIPList. Here's the JSON format:

{
    ServerIPList : [
                      <PrivateIP>            <HOSTNAME>           <REGION>  <AWS ACCOUNT>
                    { 172.00.00.00 ,ip-172-00-00-00.ec2.internal ,us-east-1,123456789123 } ,
                   ] ,
    Operation : start,
    SNowTicket : RITM00001

}

Here's my code:

import groovy.json.*
def message
pipeline {
  agent any
  options {
    buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5')
  }
  stages {
       stage('Recieve SQS Message') { steps {
       script {
            def aws = new AwsUtil()
            def success = aws.receiveSqsMessages(env.AWS_SQS_QUEUE, 1, { json ->
                message = new Util().jsonSlurper(json.Body)
                println message
                println message.ServerIPList
                println message.Operation
            result = sh (
                    script: "python ec2InstanceState.py ${message.ServerIPList} ${message.Operation}",
                    returnStdout: true
                ).trim()

output of my code:

Body:{
    "ServerIPList" : "172.24.8.73","ip-172-00-00-00.ec2.internal","us-east-1","123456789123"
    "Operation" : "start",
    "SNowTicket" : "RITM1062357"
},
"172.24.8.73","ip-172-00-00-00.ec2.internal","us-east-1","123456789123"
"start"
"python ec2InstanceState.py "172.24.8.73","ip-172-00-00-00.ec2.internal","us-east-1","123456789123" start,

Now, here i would like to grep only PrivateIp from the key: "ServerIPList". How to get it:

python ec2InstanceState.py 172.24.8.73 start


问:
appedPlainText without new line in pyqt5
I have a QPlainTextEdit box which is read-only and is used as an application console. I basically want to append a string WITHOUT a newline or \r to the PlainTextEdit widget using appendPlainText. Looking through similar quesitions, people seem to just set cursor to the end with myTextEdit->moveCursor (QTextCursor::End); and then simply append. But this did not work for me.

In my case I use pyqtSignal to append text. So, I first signal the mainwindow to set the cursor to the end and then append my string to the QPlainTextEdit widget. But it still didn't work.

Since my MainWindow have thousands of lines of code, I will just paste the pieces related to my question.

Code:

```<code>class Emitter(QThread):
    from PyQt5.QtCore import pyqtSignal, QObject, Qt
    from PyQt5.QtGui import QPixmap, QStandardItemModel, QStandardItem, QIcon
    from multiprocessing import Process, Queue, Pipe

    ConsoleSGL = pyqtSignal(str)
    consoleCursorSGL = pyqtSignal(str)

    def __init__(self, from_process: Pipe):
        super().__init__()
        self.data_from_process = from_process

    def run(self):
        while True:
            try:
                signalData = self.data_from_process.recv()
            except EOFError:
                break
            else:
                if (len(signalData) > 1 and signalData[0] == "ConsoleSGL"):
                    self.ConsoleSGL.emit(signalData[1])
                elif (len(signalData) > 1 and signalData[0] == "consoleCursorSGL"):
                    self.consoleCursorSGL.emit(signalData[1])

class MainWindow(QMainWindow, Ui_MainWindow):
    from multiprocessing import Process, Queue, Pipe
    def __init__(self, child_process_queue: Queue, emitter: Emitter):
        QMainWindow.__init__(self)
        self.process_queue = child_process_queue
        self.emitter = emitter
        self.emitter.daemon = True
        self.emitter.start()
        self.setupUi(self)
        self.pyqt5GuiCodeMain()

    def pyqt5GuiCodeMain(self):
        self.emitter.ConsoleSGL.connect(self.consoleQPlainTextEdit.appendPlainText)
        self.emitter.consoleCursorSGL.connect(self.moveDevConsoleCSR)

    def moveDevConsoleCSR(self, position):
        if position == "End":
            print("Going to end")
            self.consoleQPlainTextEdit.moveCursor(QTextCursor.End)
</code>```

When ever I want to append to my plainTextWidget, I do this:

```<code>for text in range(0, 10):
    self.signaller.send(["consoleCursorSGL", "End"])
    self.signaller.send(["ConsoleSGL", text])
</code>```

The output I get in my widget is:

```<code>0
1
2
3
4
5
6
7
8
9
</code>```

Note: I do see print("Going to end") prints in my python console output.

Can anyone tell me what am I doing wrong? or how do I append without newline using pyqt5 signals?

Body:
I have a QPlainTextEdit box which is read-only and is used as an application console. I basically want to append a string WITHOUT a newline or \r to the PlainTextEdit widget using appendPlainText. Looking through similar quesitions, people seem to just set cursor to the end with myTextEdit->moveCursor (QTextCursor::End); and then simply append. But this did not work for me.

In my case I use pyqtSignal to append text. So, I first signal the mainwindow to set the cursor to the end and then append my string to the QPlainTextEdit widget. But it still didn't work.

Since my MainWindow have thousands of lines of code, I will just paste the pieces related to my question.

Code:

class Emitter(QThread):
    from PyQt5.QtCore import pyqtSignal, QObject, Qt
    from PyQt5.QtGui import QPixmap, QStandardItemModel, QStandardItem, QIcon
    from multiprocessing import Process, Queue, Pipe

    ConsoleSGL = pyqtSignal(str)
    consoleCursorSGL = pyqtSignal(str)

    def __init__(self, from_process: Pipe):
        super().__init__()
        self.data_from_process = from_process

    def run(self):
        while True:
            try:
                signalData = self.data_from_process.recv()
            except EOFError:
                break
            else:
                if (len(signalData) > 1 and signalData[0] == "ConsoleSGL"):
                    self.ConsoleSGL.emit(signalData[1])
                elif (len(signalData) > 1 and signalData[0] == "consoleCursorSGL"):
                    self.consoleCursorSGL.emit(signalData[1])

class MainWindow(QMainWindow, Ui_MainWindow):
    from multiprocessing import Process, Queue, Pipe
    def __init__(self, child_process_queue: Queue, emitter: Emitter):
        QMainWindow.__init__(self)
        self.process_queue = child_process_queue
        self.emitter = emitter
        self.emitter.daemon = True
        self.emitter.start()
        self.setupUi(self)
        self.pyqt5GuiCodeMain()

    def pyqt5GuiCodeMain(self):
        self.emitter.ConsoleSGL.connect(self.consoleQPlainTextEdit.appendPlainText)
        self.emitter.consoleCursorSGL.connect(self.moveDevConsoleCSR)

    def moveDevConsoleCSR(self, position):
        if position == "End":
            print("Going to end")
            self.consoleQPlainTextEdit.moveCursor(QTextCursor.End)

When ever I want to append to my plainTextWidget, I do this:

for text in range(0, 10):
    self.signaller.send(["consoleCursorSGL", "End"])
    self.signaller.send(["ConsoleSGL", text])

The output I get in my widget is:

0
1
2
3
4
5
6
7
8
9

Note: I do see print("Going to end") prints in my python console output.

Can anyone tell me what am I doing wrong? or how do I append without newline using pyqt5 signals?


问:
esp32-s3-devkit-c using a seeduino 9dof gyro and accelerometer
so today i tried using my seeduino 9dof with my esp32.
When i tried using the library that seeduino has made it compiled with this error "avr/pgmspace.h no such file or directory”.

I also tried reading the raw i2c data but i only manage to read either a static 1 or 0.

When i tried using the library that seeduino has made it compiled with this error "avr/pgmspace.h no such file or directory”, this led to me changing a line that called pgmspace in the library to this:

```<code>#if defined(AVR)
#include <avr/pgmspace.h>
#else  //defined(AVR)
#include <pgmspace.h>
#endif  //defined(AVR)
</code>```

which only caused more compiler errors.

After this i tried reading the raw i2c data but did not figure out which pins the esp32 used for i2c since the pinout on the site did not list the i2c pins ( https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/_images/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg ), butt i figured out it was 19, 20 (Or every PWM pin?). However, i do get the adress from the WireScan script, but when i try to read the data i only get either 1 or 0 and it stays static.

The wirecheck script does say error 5 at 0x6B but i dont use this adress so shouldn't be a problem?

So my 2 options is to get the library working on the esp32, or figure out the i2c communication?

Thanks for any help i can get.

Also here is the code i use to read the i2c data:

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

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Wire.begin(21, 20);
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);

}

void loop() {
  // put your main code here, to run repeatedly:
  Wire.requestFrom(0x69, 6);
  float test = Wire.read();
  Serial.println(test);
  delay(100);

}

</code>```

Body:
so today i tried using my seeduino 9dof with my esp32.
When i tried using the library that seeduino has made it compiled with this error "avr/pgmspace.h no such file or directory”.

I also tried reading the raw i2c data but i only manage to read either a static 1 or 0.

When i tried using the library that seeduino has made it compiled with this error "avr/pgmspace.h no such file or directory”, this led to me changing a line that called pgmspace in the library to this:

#if defined(AVR)
#include <avr/pgmspace.h>
#else  //defined(AVR)
#include <pgmspace.h>
#endif  //defined(AVR)

which only caused more compiler errors.

After this i tried reading the raw i2c data but did not figure out which pins the esp32 used for i2c since the pinout on the site did not list the i2c pins ( https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/_images/ESP32-S3_DevKitC-1_pinlayout_v1.1.jpg ), butt i figured out it was 19, 20 (Or every PWM pin?). However, i do get the adress from the WireScan script, but when i try to read the data i only get either 1 or 0 and it stays static.

The wirecheck script does say error 5 at 0x6B but i dont use this adress so shouldn't be a problem?

So my 2 options is to get the library working on the esp32, or figure out the i2c communication?

Thanks for any help i can get.

Also here is the code i use to read the i2c data:

#include <Wire.h>

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Wire.begin(21, 20);
  pinMode(8, OUTPUT);
  digitalWrite(8, HIGH);

}

void loop() {
  // put your main code here, to run repeatedly:
  Wire.requestFrom(0x69, 6);
  float test = Wire.read();
  Serial.println(test);
  delay(100);

}


问:
Call custom method for authorization for each endpoint or resource in Quarkus
I have an application with 2 entities : A and B.

Each of these entities contain a "Workspace" :

```<code>@Entity
class A {
  private Workspace workspace;
}

@Entity
class B {
  private Workspace workspace;
}
</code>```

For each request that comes in like a GET <api>/resourceA or a POST <api>/resourceB/{id}/createSomething, we need to check that the caller (that is logged in through Keycloak and has a JWT) has access to the Workspace that A is part of (or B, in the latter case). It's all "dynamic" as it's based on the ID of the specific object A.

So, for each endpoint (or each Resource, might be all that's needed), we need to call a method that is specific to that endpoint/Resource. We cannot do this with just "Roles", because we need to have that specific check on the IDs, like :

```<code>A.getWorkspace().isAccessibleBy(theCallingUser)
</code>```

I know Spring Security has specific methods like "hasRole()" and you can call specific code in the @PreAuthorize annotations, but I haven't seen the same in Quarkus.

Body:
I have an application with 2 entities : A and B.

Each of these entities contain a "Workspace" :

@Entity
class A {
  private Workspace workspace;
}

@Entity
class B {
  private Workspace workspace;
}

For each request that comes in like a GET <api>/resourceA or a POST <api>/resourceB/{id}/createSomething, we need to check that the caller (that is logged in through Keycloak and has a JWT) has access to the Workspace that A is part of (or B, in the latter case). It's all "dynamic" as it's based on the ID of the specific object A.

So, for each endpoint (or each Resource, might be all that's needed), we need to call a method that is specific to that endpoint/Resource. We cannot do this with just "Roles", because we need to have that specific check on the IDs, like :

A.getWorkspace().isAccessibleBy(theCallingUser)

I know Spring Security has specific methods like "hasRole()" and you can call specific code in the @PreAuthorize annotations, but I haven't seen the same in Quarkus.


问:
How to correctly use Transactional
In my jhipster gateway application I have a repository (extends R2dbcRepository) a method which should return me every value connected to an id. But I am getting the following error:

```<code>Cannot apply reactive transaction to non-reactive return type: interface java.util.List
</code>```

I tried adding the transactional annotation but it did not help. Could someone take a look and tell me what my mistake is.

```<code>@Service
@Transactional
public class ReceiptService {

    private final Logger log = LoggerFactory.getLogger(ReceiptService.class);

    private final ReceiptRepository receiptRepository;

    private final RceiptRepository rceiptRepository;
    private final ReceiptMapper receiptMapper;

    public ReceiptService(ReceiptRepository receiptRepository, RceiptRepository rceiptRepository, ReceiptMapper receiptMapper) {
        this.receiptRepository = receiptRepository;
        this.rceiptRepository = rceiptRepository;
        //   this.rceiptRepository = rceiptRepository;
        this.receiptMapper = receiptMapper;
    }

    @Transactional
    public List<ReceiptDTO> findByCompany(Long companyUserID) {
        log.debug("Request to get all Receipts by a company");
        return receiptRepository.findReceiptsByCompanyId(companyUserID).stream().map(receiptMapper::toDto).collect(Collectors.toList());
    }

}
</code>```

Repository:

```<code>@Repository
public interface ReceiptRepository extends R2dbcRepository<Receipt, Long>, ReceiptRepositoryInternal {
    @Query("SELECT * FROM receipt entity WHERE entity.user_receipt_id = :id")
    Flux<Receipt> findByUser_receipt(Long id);

    @Query("SELECT * FROM receipt entity WHERE entity.user_receipt_id IS NULL")
    Flux<Receipt> findAllWhereUser_receiptIsNull();

    // just to avoid having unambigous methods
    @Override
    Flux<Receipt> findAll();

    @Override
    List<Receipt> findReceiptsByCompanyId(Long id);

    @Override
    Mono<Receipt> findById(Long id);

    @Override
    <S extends Receipt> Mono<S> save(S entity);
}

interface ReceiptRepositoryInternal{
    <S extends Receipt> Mono<S> insert(S entity);
    <S extends Receipt> Mono<S> save(S entity);
    Mono<Integer> update(Receipt entity);

    Flux<Receipt> findAll();
    Mono<Receipt> findById(Long id);
    Flux<Receipt> findAllBy(Pageable pageable);
    Flux<Receipt> findAllBy(Pageable pageable, Criteria criteria);

    List<Receipt> findReceiptsByCompanyId(Long id);

}
</code>```

Controller:

```<code>@RestController
@RequestMapping("/api")
public class ReceiptResource {

    private final Logger log = LoggerFactory.getLogger(ReceiptResource.class);

    private static final String ENTITY_NAME = "receipt";

    @Value("${jhipster.clientApp.name}")
    private String applicationName;

    private final ReceiptService receiptService;

    private final ReceiptRepository receiptRepository;

    private final UserRepository userRepository;

    public ReceiptResource(ReceiptService receiptService, ReceiptRepository receiptRepository, UserRepository userRepository) {
        this.receiptService = receiptService;
        this.receiptRepository = receiptRepository;
        this.userRepository = userRepository;
    }

    /**
     * {@code POST  /receipts} : Create a new receipt.
     *
     * @param receiptDTO the receiptDTO to create.
     * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new receiptDTO, or with status {@code 400 (Bad Request)} if the receipt has already an ID.
     * @throws URISyntaxException if the Location URI syntax is incorrect.
     */

    @PostMapping("/receipts")
    public Mono<ResponseEntity<ReceiptDTO>> createReceipt(@RequestBody ReceiptDTO receiptDTO) throws URISyntaxException {
        log.debug("REST request to save Receipt : {}", receiptDTO);
        if (receiptDTO.getId() != null) {
            throw new BadRequestAlertException("A new receipt cannot already have an ID", ENTITY_NAME, "idexists");
        }
        return receiptService
            .save(receiptDTO)
            .map(result -> {
                try {
                    return ResponseEntity
                        .created(new URI("/api/receipts/" + result.getId()))
                        .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
                        .body(result);
                } catch (URISyntaxException e) {
                    throw new RuntimeException(e);
                }
            });
    }

    @GetMapping("/receipts/byUserId")
    public List<ReceiptDTO> getAllReceiptsByCompanyId(@RequestParam Long companyId) {
        log.debug("REST request to get all Receipts");

        return receiptService.findByCompany(companyId);
    }

}
</code>```

Complete Service class:

```<code>@Service
@Transactional
public class ReceiptService {

    private final Logger log = LoggerFactory.getLogger(ReceiptService.class);

    private final ReceiptRepository receiptRepository;

    private final ReceiptMapper receiptMapper;

    public ReceiptService(ReceiptRepository receiptRepository, ReceiptMapper receiptMapper) {
        this.receiptRepository = receiptRepository;
        this.receiptMapper = receiptMapper;
    }

    /**
     * Save a receipt.
     *
     * @param receiptDTO the entity to save.
     * @return the persisted entity.
     */
    public Mono<ReceiptDTO> save(ReceiptDTO receiptDTO) {
        log.debug("Request to save Receipt : {}", receiptDTO);
        return receiptRepository.save(receiptMapper.toEntity(receiptDTO)).map(receiptMapper::toDto);
    }

    /**
     * Partially update a receipt.
     *
     * @param receiptDTO the entity to update partially.
     * @return the persisted entity.
     */
    public Mono<ReceiptDTO> partialUpdate(ReceiptDTO receiptDTO) {
        log.debug("Request to partially update Receipt : {}", receiptDTO);

        return receiptRepository
            .findById(receiptDTO.getId())
            .map(existingReceipt -> {
                receiptMapper.partialUpdate(existingReceipt, receiptDTO);

                return existingReceipt;
            })
            .flatMap(receiptRepository::save)
            .map(receiptMapper::toDto);
    }

    @Transactional
    public List<ReceiptDTO> findByCompany(Long companyUserID) {
        log.debug("Request to get all Receipts by a company");
        return receiptRepository.findReceiptsByCompanyId(companyUserID).stream().map(receiptMapper::toDto).collect(Collectors.toList());
    }

//    public List<ReceiptDTO> findByCompanyJpa(Long companyUserID) {
//        log.debug("Request to get all Receipts by a company");
//        return rceiptRepository.findReceiptsByCompanyId(companyUserID).stream().map(receiptMapper::toDto).collect(Collectors.toList());
//    }

    /**
     * Get all the receipts.
     *
     * @return the list of entities.
     */
    @Transactional(readOnly = true)
    public Flux<ReceiptDTO> findAll() {
        log.debug("Request to get all Receipts");
        return receiptRepository.findAll().map(receiptMapper::toDto);
    }

    /**
     * Returns the number of receipts available.
     *
     * @return the number of entities in the database.
     */
    public Mono<Long> countAll() {
        return receiptRepository.count();
    }

    /**
     * Get one receipt by id.
     *
     * @param id the id of the entity.
     * @return the entity.
     */
    @Transactional(readOnly = true)
    public Mono<ReceiptDTO> findOne(Long id) {
        log.debug("Request to get Receipt : {}", id);
        return receiptRepository.findById(id).map(receiptMapper::toDto);
    }

    /**
     * Delete the receipt by id.
     *
     * @param id the id of the entity.
     * @return a Mono to signal the deletion
     */
    public Mono<Void> delete(Long id) {
        log.debug("Request to delete Receipt : {}", id);
        return receiptRepository.deleteById(id);
    }
}
</code>```

Error:

```<code>  java.lang.IllegalStateException: Cannot apply reactive transaction to non-reactive return type: interface java.util.List
    at org.springframework.transaction.interceptor.TransactionAspectSupport.lambda$invokeWithinTransaction$0(TransactionAspectSupport.java:359)
    at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
    at com.nosi.gateway.service.ReceiptService$$EnhancerBySpringCGLIB$$a802f8a9.findByCompany(<generated>)
    at com.nosi.gateway.web.rest.ReceiptResource.getAllReceiptsByCompanyId(ReceiptResource.java:85)
    at com.nosi.gateway.web.rest.ReceiptResource$$FastClassBySpringCGLIB$$a680ab7a.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
    at com.nosi.gateway.aop.logging.LoggingAspect.logAround(LoggingAspect.java:103)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
</code>```

Title: How to correctly use Transactional

Body:
In my jhipster gateway application I have a repository (extends R2dbcRepository) a method which should return me every value connected to an id. But I am getting the following error:

Cannot apply reactive transaction to non-reactive return type: interface java.util.List

I tried adding the transactional annotation but it did not help. Could someone take a look and tell me what my mistake is.

@Service
@Transactional
public class ReceiptService {

    private final Logger log = LoggerFactory.getLogger(ReceiptService.class);

    private final ReceiptRepository receiptRepository;

    private final RceiptRepository rceiptRepository;
    private final ReceiptMapper receiptMapper;

    public ReceiptService(ReceiptRepository receiptRepository, RceiptRepository rceiptRepository, ReceiptMapper receiptMapper) {
        this.receiptRepository = receiptRepository;
        this.rceiptRepository = rceiptRepository;
        //   this.rceiptRepository = rceiptRepository;
        this.receiptMapper = receiptMapper;
    }

    @Transactional
    public List<ReceiptDTO> findByCompany(Long companyUserID) {
        log.debug("Request to get all Receipts by a company");
        return receiptRepository.findReceiptsByCompanyId(companyUserID).stream().map(receiptMapper::toDto).collect(Collectors.toList());
    }

}

Repository:

@Repository
public interface ReceiptRepository extends R2dbcRepository<Receipt, Long>, ReceiptRepositoryInternal {
    @Query("SELECT * FROM receipt entity WHERE entity.user_receipt_id = :id")
    Flux<Receipt> findByUser_receipt(Long id);

    @Query("SELECT * FROM receipt entity WHERE entity.user_receipt_id IS NULL")
    Flux<Receipt> findAllWhereUser_receiptIsNull();

    // just to avoid having unambigous methods
    @Override
    Flux<Receipt> findAll();

    @Override
    List<Receipt> findReceiptsByCompanyId(Long id);

    @Override
    Mono<Receipt> findById(Long id);

    @Override
    <S extends Receipt> Mono<S> save(S entity);
}

interface ReceiptRepositoryInternal{
    <S extends Receipt> Mono<S> insert(S entity);
    <S extends Receipt> Mono<S> save(S entity);
    Mono<Integer> update(Receipt entity);

    Flux<Receipt> findAll();
    Mono<Receipt> findById(Long id);
    Flux<Receipt> findAllBy(Pageable pageable);
    Flux<Receipt> findAllBy(Pageable pageable, Criteria criteria);

    List<Receipt> findReceiptsByCompanyId(Long id);

}

Controller:

@RestController
@RequestMapping("/api")
public class ReceiptResource {

    private final Logger log = LoggerFactory.getLogger(ReceiptResource.class);

    private static final String ENTITY_NAME = "receipt";

    @Value("${jhipster.clientApp.name}")
    private String applicationName;

    private final ReceiptService receiptService;

    private final ReceiptRepository receiptRepository;

    private final UserRepository userRepository;

    public ReceiptResource(ReceiptService receiptService, ReceiptRepository receiptRepository, UserRepository userRepository) {
        this.receiptService = receiptService;
        this.receiptRepository = receiptRepository;
        this.userRepository = userRepository;
    }

    /**
     * {@code POST  /receipts} : Create a new receipt.
     *
     * @param receiptDTO the receiptDTO to create.
     * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new receiptDTO, or with status {@code 400 (Bad Request)} if the receipt has already an ID.
     * @throws URISyntaxException if the Location URI syntax is incorrect.
     */

    @PostMapping("/receipts")
    public Mono<ResponseEntity<ReceiptDTO>> createReceipt(@RequestBody ReceiptDTO receiptDTO) throws URISyntaxException {
        log.debug("REST request to save Receipt : {}", receiptDTO);
        if (receiptDTO.getId() != null) {
            throw new BadRequestAlertException("A new receipt cannot already have an ID", ENTITY_NAME, "idexists");
        }
        return receiptService
            .save(receiptDTO)
            .map(result -> {
                try {
                    return ResponseEntity
                        .created(new URI("/api/receipts/" + result.getId()))
                        .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
                        .body(result);
                } catch (URISyntaxException e) {
                    throw new RuntimeException(e);
                }
            });
    }

    @GetMapping("/receipts/byUserId")
    public List<ReceiptDTO> getAllReceiptsByCompanyId(@RequestParam Long companyId) {
        log.debug("REST request to get all Receipts");

        return receiptService.findByCompany(companyId);
    }

}

Complete Service class:

@Service
@Transactional
public class ReceiptService {

    private final Logger log = LoggerFactory.getLogger(ReceiptService.class);

    private final ReceiptRepository receiptRepository;

    private final ReceiptMapper receiptMapper;

    public ReceiptService(ReceiptRepository receiptRepository, ReceiptMapper receiptMapper) {
        this.receiptRepository = receiptRepository;
        this.receiptMapper = receiptMapper;
    }

    /**
     * Save a receipt.
     *
     * @param receiptDTO the entity to save.
     * @return the persisted entity.
     */
    public Mono<ReceiptDTO> save(ReceiptDTO receiptDTO) {
        log.debug("Request to save Receipt : {}", receiptDTO);
        return receiptRepository.save(receiptMapper.toEntity(receiptDTO)).map(receiptMapper::toDto);
    }

    /**
     * Partially update a receipt.
     *
     * @param receiptDTO the entity to update partially.
     * @return the persisted entity.
     */
    public Mono<ReceiptDTO> partialUpdate(ReceiptDTO receiptDTO) {
        log.debug("Request to partially update Receipt : {}", receiptDTO);

        return receiptRepository
            .findById(receiptDTO.getId())
            .map(existingReceipt -> {
                receiptMapper.partialUpdate(existingReceipt, receiptDTO);

                return existingReceipt;
            })
            .flatMap(receiptRepository::save)
            .map(receiptMapper::toDto);
    }

    @Transactional
    public List<ReceiptDTO> findByCompany(Long companyUserID) {
        log.debug("Request to get all Receipts by a company");
        return receiptRepository.findReceiptsByCompanyId(companyUserID).stream().map(receiptMapper::toDto).collect(Collectors.toList());
    }

//    public List<ReceiptDTO> findByCompanyJpa(Long companyUserID) {
//        log.debug("Request to get all Receipts by a company");
//        return rceiptRepository.findReceiptsByCompanyId(companyUserID).stream().map(receiptMapper::toDto).collect(Collectors.toList());
//    }

    /**
     * Get all the receipts.
     *
     * @return the list of entities.
     */
    @Transactional(readOnly = true)
    public Flux<ReceiptDTO> findAll() {
        log.debug("Request to get all Receipts");
        return receiptRepository.findAll().map(receiptMapper::toDto);
    }

    /**
     * Returns the number of receipts available.
     *
     * @return the number of entities in the database.
     */
    public Mono<Long> countAll() {
        return receiptRepository.count();
    }

    /**
     * Get one receipt by id.
     *
     * @param id the id of the entity.
     * @return the entity.
     */
    @Transactional(readOnly = true)
    public Mono<ReceiptDTO> findOne(Long id) {
        log.debug("Request to get Receipt : {}", id);
        return receiptRepository.findById(id).map(receiptMapper::toDto);
    }

    /**
     * Delete the receipt by id.
     *
     * @param id the id of the entity.
     * @return a Mono to signal the deletion
     */
    public Mono<Void> delete(Long id) {
        log.debug("Request to delete Receipt : {}", id);
        return receiptRepository.deleteById(id);
    }
}

Error:

  java.lang.IllegalStateException: Cannot apply reactive transaction to non-reactive return type: interface java.util.List
    at org.springframework.transaction.interceptor.TransactionAspectSupport.lambda$invokeWithinTransaction$0(TransactionAspectSupport.java:359)
    at java.base/java.util.concurrent.ConcurrentMap.computeIfAbsent(ConcurrentMap.java:330)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692)
    at com.nosi.gateway.service.ReceiptService$$EnhancerBySpringCGLIB$$a802f8a9.findByCompany(<generated>)
    at com.nosi.gateway.web.rest.ReceiptResource.getAllReceiptsByCompanyId(ReceiptResource.java:85)
    at com.nosi.gateway.web.rest.ReceiptResource$$FastClassBySpringCGLIB$$a680ab7a.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:779)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.aspectj.AspectJAfterThrowingAdvice.invoke(AspectJAfterThrowingAdvice.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750)
    at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
    at com.nosi.gateway.aop.logging.LoggingAspect.logAround(LoggingAspect.java:103)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)


问:
GApplication OptionArgFunc callback with user data, as part of main option group?
Writing a Gtk (3.0, for the moment) application's main() function and installing the standard GLib/Gio GApplication scaffolding, I've hit a snag when it comes to command-line argument processing.

I'm already convinced I don't want to handle the commandline myself, because that's exactly what the toolkits are supposed to be there for. At least, in theory. So the command line is set up by defining a GOptionEntry array and passing it to g_application_add_main_option_entries() in the usual fashion:

GOptionEntry options[] =
{
    { "verbose", 'v', 0,
        G_OPTION_ARG_NONE, &opt_verbose,
        "Be verbose", NULL },
    { "otherarg", 'o', 0,
        G_OPTION_ARG_STRING, &opt_other,
        "Secret", NULL },
    { NULL }
};
app = gtk_application_new("org.me.myapp", G_APPLICATION_NON_UNIQUE);
g_application_add_main_option_entries(G_APPLICATION(app), options);
```
<p>So far, so good. But now I want to include a <code>--debug</code> flag, and I'd like to handle that with an <code>OptionArgFunc</code> callback so that it can modify the <code>G_MESSAGES_DEBUG</code> environment variable to append the <code>G_LOG_DOMAIN</code> when debugging is enabled. (I'd rather not write my own log handling, either.)</p>
<p>That part's also easy enough, using an argument-processing callback:</p>
<pre class="lang-c prettyprint-override"><code>gboolean
enable_debug (const gchar* option_name, const gchar* value,
              gpointer data, GError** error)
{
    // ...
}
GOptionEntry options[] =
{
    { "verbose", 'v', 0,
        G_OPTION_ARG_NONE, &opt_verbose,
        "Be verbose", NULL },
    { "otherarg", 'o', 0,
        G_OPTION_ARG_STRING, &opt_other,
        "Secret", NULL },
    { "debug", 'd', G_OPTION_FLAG_NO_ARG,
        G_OPTION_ARG_CALLBACK, &enable_debug,
        "Enable debug output", NULL },
    { NULL }
};
</code>```

But, now say I want to pass some user data to enable_debug() — actually have that gpointer data set to something other than NULL.

According to the docs, data carries...

User data added to the GOptionGroup containing the option when it was created with g_option_group_new()

But I'm not using g_option_group_new().

I'd be happy to use g_option_group_new(), but AFAICT there's no way to create the main GApplication option group "by hand" (by calling g_option_group_new()), it's only created implicitly by calling g_application_add_main_option_entries() which doesn't allow user data to be attached to the group.

And if I were to create a new GOptionGroup for the --debug option, using g_option_group_new() followed by g_application_add_option_group(), --debug would be relegated to a different option group than the rest of my arguments, and it wouldn't be shown in the main --help output — the user would have to run myapp --help-debugging (or whatever I named it) in order to see the --debug flag in the argument synopsis.

Do I have all that right? Are GOptionArgFunc callbacks that take user data really mutually exclusive with arguments that are part of the application's main option group? Is there a reason why that would be the case, or is it just a weird hole in the API?

Body:
Writing a Gtk (3.0, for the moment) application's main() function and installing the standard GLib/Gio GApplication scaffolding, I've hit a snag when it comes to command-line argument processing.

I'm already convinced I don't want to handle the commandline myself, because that's exactly what the toolkits are supposed to be there for. At least, in theory. So the command line is set up by defining a GOptionEntry array and passing it to g_application_add_main_option_entries() in the usual fashion:

GOptionEntry options[] =
{
    { "verbose", 'v', 0,
        G_OPTION_ARG_NONE, &opt_verbose,
        "Be verbose", NULL },
    { "otherarg", 'o', 0,
        G_OPTION_ARG_STRING, &opt_other,
        "Secret", NULL },
    { NULL }
};
app = gtk_application_new("org.me.myapp", G_APPLICATION_NON_UNIQUE);
g_application_add_main_option_entries(G_APPLICATION(app), options);

So far, so good. But now I want to include a --debug flag, and I'd like to handle that with an OptionArgFunc callback so that it can modify the G_MESSAGES_DEBUG environment variable to append the G_LOG_DOMAIN when debugging is enabled. (I'd rather not write my own log handling, either.)

That part's also easy enough, using an argument-processing callback:

gboolean
enable_debug (const gchar* option_name, const gchar* value,
              gpointer data, GError** error)
{
    // ...
}
GOptionEntry options[] =
{
    { "verbose", 'v', 0,
        G_OPTION_ARG_NONE, &opt_verbose,
        "Be verbose", NULL },
    { "otherarg", 'o', 0,
        G_OPTION_ARG_STRING, &opt_other,
        "Secret", NULL },
    { "debug", 'd', G_OPTION_FLAG_NO_ARG,
        G_OPTION_ARG_CALLBACK, &enable_debug,
        "Enable debug output", NULL },
    { NULL }
};

But, now say I want to pass some user data to enable_debug() — actually have that gpointer data set to something other than NULL.

According to the docs, data carries...

User data added to the GOptionGroup containing the option when it was created with g_option_group_new()

But I'm not using g_option_group_new().

I'd be happy to use g_option_group_new(), but AFAICT there's no way to create the main GApplication option group "by hand" (by calling g_option_group_new()), it's only created implicitly by calling g_application_add_main_option_entries() which doesn't allow user data to be attached to the group.

And if I were to create a new GOptionGroup for the --debug option, using g_option_group_new() followed by g_application_add_option_group(), --debug would be relegated to a different option group than the rest of my arguments, and it wouldn't be shown in the main --help output — the user would have to run myapp --help-debugging (or whatever I named it) in order to see the --debug flag in the argument synopsis.

Do I have all that right? Are GOptionArgFunc callbacks that take user data really mutually exclusive with arguments that are part of the application's main option group? Is there a reason why that would be the case, or is it just a weird hole in the API?


问:
How do I resize the edit menu drop down?
I have a SwiftUI drop down menu in a view. The drop down that appears when the menu is selected is too large. Does anyone know how to resize it? I tried adding a frame after } on the menu block but that doesn't result in any changes.</p>
```<code>Menu("Distance") {
    Button("10mile", action: viewModel.placeOrder)
    Button("20mile", action: viewModel.adjustOrder)
    Button("40mile", action: viewModel.cancelOrder)
}
.offset(x: 28)
.foregroundColor(.gray)
</code>```

Body:
I have a SwiftUI drop down menu in a view. The drop down that appears when the menu is selected is too large. Does anyone know how to resize it? I tried adding a frame after } on the menu block but that doesn't result in any changes.

Menu("Distance") {
    Button("10mile", action: viewModel.placeOrder)
    Button("20mile", action: viewModel.adjustOrder)
    Button("40mile", action: viewModel.cancelOrder)
}
.offset(x: 28)
.foregroundColor(.gray)


问:
d3.csv() is returning my index.html file instead of the csv file
I am trying to use d3.csv() to read in my data. When logging my data using console.log(data), instead of returning the contents of the csv, the console is showing each line of my index.html file.

Current code:

import * as d3 from "d3";

d3.csv('/data/nobel_final.csv').then(function(data) {
    console.log(data);
})

```

Output:

I installed d3 via npm. I attached my js file in a script tag before the body tag in my html. I have tried using http-server and parcel and both result in the same output. I have tried everthing in this so post and still haven't had any luck.

Body:
I am trying to use d3.csv() to read in my data. When logging my data using console.log(data), instead of returning the contents of the csv, the console is showing each line of my index.html file.

Current code:

import * as d3 from "d3";

d3.csv('/data/nobel_final.csv').then(function(data) {
    console.log(data);
})

Output:

I installed d3 via npm. I attached my js file in a script tag before the body tag in my html. I have tried using http-server and parcel and both result in the same output. I have tried everthing in this so post and still haven't had any luck.


问:
Get a Copy of MQ Message without impacting current producer and consumer
Is there a way to read the MQ message without impacting the current producer and consumer?

We have a consumer already to read from a MQ, but we want to feed the same messages in the MQ to some other places. Is there way to do that without touching the MQ producer nor the existing consumer?

I searched around and found there's something called queue browse. Can I set up another consumer for this MQ and only do browsing? Will both the old and new consumer be able to get all messages?

The producer is not owned by us, so can't change the configuration of it.

So the best option is to not touch producer + consumer; But if no other choice, we can try modify a bit of the existing consumer.

Are there any ways? Thanks a lot!


问:
lld-link is showing error (undefined symbol : EFI_LOADED_IMAGE_PROTOCOL_GUID)
I am making UEFI Bootloader (UEFI Application), by last version of clang and linked by lld-link.
i need to use EFI_LOADED_IMAGE_PROTOCOL for load file, I used EFI_LOADED_IMAGE_PROTOCOL_GUID.
but lld-link is showing
undefined symbol : EFI_LOADED_IMAGE_PROTOCOL_GUID.

I am making uefi bootloader (uefi application), by C, i just compiled to clang and linked by lld-link.

!! not used edk II (can't compile. please compile edk 2 and send me)

i add command 'load kernel and logging text 'Hello, world!' (print),
but lld-link shows error.
"undefined symbol : EFI_LOADED_IMAGE_PROTOCOL_GUID (in getdiskimage)"

I tried copying example, but it doesn't work.

I used gnu-efi library in github.


问:
Spinnaker multiple auto-triggers for multi-image Helm Chart
Hello Ladies & Gentlemen,
My Helm Chart consists of 9 docker images. I would like to be able to deploy it to 4 environments by using Spinnaker which is installed on Ubuntu. I use GitHub & ECR auto-triggers; images are in ECR, Helm Chart is in GitHub.

values.yaml is something like that:

```<code>image:
    repository: 123123123.dkr.ecr.eu-central-1.amazonaws.com/docker/app1
    tag: ""
image:
    repository: 123123123.dkr.ecr.eu-central-1.amazonaws.com/docker/app3
    tag: ""
image:
    repository: 123123123.dkr.ecr.eu-central-1.amazonaws.com/docker/app2
    tag: ""
</code>```

My pipeline is auto-triggered by multiple ECR repositories, multiple images.

Triggers work, Spinnaker gets the payload and deployment starts.

The problem is that I am not be able to place the image/tag which is transmitted by ECR webhook to the right place in the baked manifest.

For example;
Spinnaker Igor gets image information from ECR webhook something like that:

Found 1 new images for svc-spinnaker-ecr. Images: [{imageId=igor:dockerRegistry:v2:svc-spinnaker-ecr:docker/app3:0.1.0-dev.9, sendEvent=true}]

This string app3:0.1.0-dev.9 or this one 0.1.0-dev.9 must be placed/replaced in baked manifest in the right line above.

How can I accomplish it? Could you please advise?

Thanks & Reagrds

I tried following SpEL expressions:

```<code>${ #stage('Find Image from Staging Environment').outputs.artifacts[0].reference.split(':')[1] }
${ trigger['tag']}
${ #triggerResolvedArtifactByType("docker/image")["reference"]}
${ #stage('bake')['outputs']['artifacts'].?[type == 'docker/image'].![reference] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference.split(':')[1]] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference.replace("[", "").replace("]", "").split(':')[1]] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference.split(':')[1]] }
</code>```

...but none of them has image name constraint so they are not usable as variable or override.

Body:
Hello Ladies & Gentlemen,
My Helm Chart consists of 9 docker images. I would like to be able to deploy it to 4 environments by using Spinnaker which is installed on Ubuntu. I use GitHub & ECR auto-triggers; images are in ECR, Helm Chart is in GitHub.

values.yaml is something like that:

image:
    repository: 123123123.dkr.ecr.eu-central-1.amazonaws.com/docker/app1
    tag: ""
image:
    repository: 123123123.dkr.ecr.eu-central-1.amazonaws.com/docker/app3
    tag: ""
image:
    repository: 123123123.dkr.ecr.eu-central-1.amazonaws.com/docker/app2
    tag: ""

My pipeline is auto-triggered by multiple ECR repositories, multiple images.

Triggers work, Spinnaker gets the payload and deployment starts.

The problem is that I am not be able to place the image/tag which is transmitted by ECR webhook to the right place in the baked manifest.

For example;
Spinnaker Igor gets image information from ECR webhook something like that:

Found 1 new images for svc-spinnaker-ecr. Images: [{imageId=igor:dockerRegistry:v2:svc-spinnaker-ecr:docker/app3:0.1.0-dev.9, sendEvent=true}]

This string app3:0.1.0-dev.9 or this one 0.1.0-dev.9 must be placed/replaced in baked manifest in the right line above.

How can I accomplish it? Could you please advise?

Thanks & Reagrds

I tried following SpEL expressions:

${ #stage('Find Image from Staging Environment').outputs.artifacts[0].reference.split(':')[1] }
${ trigger['tag']}
${ #triggerResolvedArtifactByType("docker/image")["reference"]}
${ #stage('bake')['outputs']['artifacts'].?[type == 'docker/image'].![reference] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference.split(':')[1]] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference.replace("[", "").replace("]", "").split(':')[1]] }
${ trigger['artifacts'].?[type == 'docker/image'].![reference.split(':')[1]] }

...but none of them has image name constraint so they are not usable as variable or override.


问:
Reproduce satellite imagery tilted at 45 degree like Google Maps does
I would like to replicate the 45 degree tilted view from the google maps javascript API.
For exemple, see this page from the google maps documentation : https://developers.google.com/maps/documentation/javascript/examples/aerial-simple

To do that i have backwards engineered the API to get the formulas that convert latitude and longitude coordinates into tile coordinates.

However, when I apply this formula, I get some misplaced rows of tiles.

//This code compute tiles numbers for 45 deg

function main(args) {
    //https://khms1.googleapis.com/kh?v=150&hl=fr&deg=0&x=41981&y=103113&z=18
    let longx = parseFloat(args.lng);
    let latx = parseFloat(args.lat);

    let ob1 = getLocation(latx, longx, args.z);
    let returnObject = new Object;
    returnObject.x = ob1.oa.toString();
    returnObject.y = ob1.pa.toString();
    returnObject.z = ob1.ya.toString();
    return returnObject;
}

function getLocation(lat, lng, zoom) {
    //this function from location return 45 deg tile number
    const degresinclinaison = 45;
    const heading = 0;
    const tileSize = 256;

    const powTwoZoomLevel = Math.pow(2, zoom);
    //compute the location to point
    let point = fromLatLngToPoint(lat, lng);
    let tileLocation = pointToTileNumber(point.x, point.y);
    return tileLocation;

    function fromLatLngToPoint(lat_args, lng_args) {
        //extract from the google api, i dont now what each variable is
        let h = 256 / 360; //0.711111111111111
        let a = Math.sin((lat_args * Math.PI / 180));
        let c = tileSize / (2 * Math.PI);

        let x = 128 + lng_args * h;
        let y = 128 + 0.5 * Math.log((1 + a) / (1 - a)) * -c;

        let returnObject = new Object;
        returnObject.x = x;
        returnObject.y = y;
        return returnObject;
    }

    function fromPointToLatLng(x_args, y_args) {
        //extract from the google api
        let c = tileSize / (2 * Math.PI);
        let h = 256 / 360; //0.711111111111111

        let lat = (180 * (2 * Math.atan(Math.exp((y_args - 128) / -c)) - Math.PI / 2) / Math.PI);
        let lng = (x_args - 128) / h;
        let returnObject = new Object;
        returnObject.lat = lat;
        returnObject.lng = lng;
        return returnObject;
    }

    function pointToTileNumber(x_args, y_args) {
        //this function convert the point to tilenumber
        let axeRotate = rotate(1, x_args, y_args);
        let x2 = axeRotate.X;
        let y2 = axeRotate.Y;
        //variable name is the same in the api. this is more simple to use them to.
        let h = Math.cos(degresinclinaison / 180 * Math.PI);
        var oa = Math.floor(x2 * powTwoZoomLevel / tileSize);
        var pa = Math.floor(powTwoZoomLevel * (.5 + (y2 / tileSize - .5) * h));
        var ya = zoom;

        return {
            oa: oa, //d(b.h * e / a.size.fa),
            pa: pa, //d(e * (.5 + (b.j / a.size.ha - .5) * a.h)),
            ya: ya //c
        }
    }

    function rotate(nbr, x1, y1) {
        //extract from the api, not working actually......
        let axeX = x1 //b.h;
        let axeY = y1 //b.j;
        switch ((360 + heading * nbr) % 360) {
            case 90:
                axeX = y1;
                axeY = tileSize - x1;
                break;
            case 180:
                axeX = tileSize - x1;
                axeY = tileSize - y1;
                break;
            case 270:
                axeX = tileSize - y1;
                axeY = x1
        }

        let returnObject = new Object;
        returnObject.X = axeX;
        returnObject.Y = axeY;
        return returnObject
    };
}

//This code show tiles on the html

let maptype = new Object;
maptype.satelite = new Object;
maptype.satelite.element = document.querySelector(".map_container .satelite");
maptype.satelite.url = "https://khms1.googleapis.com/kh?v=937&hl=fr&x={x}&y={y}&z={z}";

maptype.oblique = new Object;
maptype.oblique.element = document.querySelector(".map_container .oblique");
maptype.oblique.url = "https://khms1.googleapis.com/kh?v=150&hl=fr&deg=0&x={x}&y={y}&z={z}"

function createMapBase() {
    let view_tile_size = 30; //tile size of each tiles
    let map_container = document.querySelector(".map_container");
    let nbr_tiles_columns = Math.ceil(map_container.getBoundingClientRect().width / view_tile_size);
    let nbr_tiles_rows = Math.ceil(map_container.getBoundingClientRect().height / view_tile_size);
    createImgArray("satelite");
    createImgArray("oblique");

    //function createImgArray : load a array of img element into a container and load the url
    function createImgArray(type) {
        for (let tiles_rows = 0; tiles_rows < nbr_tiles_rows; tiles_rows++) {
            for (let tiles_columns = 0; tiles_columns < nbr_tiles_columns; tiles_columns++) {
                var img_element = document.createElement("img");
                if (type == "satelite") {
                    img_element.setAttribute("src", getMercatorUrl(maptype[type].url, tiles_rows, tiles_columns));
                } else if (type == "oblique") {
                    img_element.setAttribute("src", getObliqueUrl(maptype[type].url, tiles_rows, tiles_columns));
                } else {
                    console.warn("Error, this maptype is not supported : " + type);
                }

                img_element.style = "position : absolute; top:" + tiles_rows * view_tile_size + "px; left:" + tiles_columns * view_tile_size + "px; width:" + view_tile_size + "px";

                maptype[type].element.appendChild(img_element);
            }
        }
    }

}

function getMercatorUrl(base_url, row, column) {
    //get the mercator tile number -> the top-right tile
    let tiles_number = getMercatorTileNumberFromLocation();
    //generate the src url
    let final_url = base_url;
    final_url = final_url.replaceAll("{x}", tiles_number.x + column);
    final_url = final_url.replaceAll("{y}", tiles_number.y + row);
    final_url = final_url.replaceAll("{z}", tiles_number.z);
    return final_url;
}

function getObliqueUrl(base_url, row, column) {
    //get the mercator tile number -> the top-right tile
    let first_tile_number = getMercatorTileNumberFromLocation();
    //increment and get back the top-right location of the tile
    let converted_location = getLocationFromMercatorTileNumber(first_tile_number.x + column, first_tile_number.y + row, first_tile_number.z);
    //convert the location to 45 deg tiles number
    let tiles_number = main(converted_location);
    //generate the src url
    let final_url = base_url;
    final_url = final_url.replaceAll("{x}", tiles_number.x);
    final_url = final_url.replaceAll("{y}", tiles_number.y);
    final_url = final_url.replaceAll("{z}", tiles_number.z);
    return final_url;

}

function obliqueChangeVisibility() {
    //triggered when check checkbox
    if (document.getElementById("is_oblique_view_visible").checked) {
        maptype.oblique.element.style.visibility = "visible";
    } else {
        maptype.oblique.element.style.visibility = "hidden";
    }
}

function locationPresetChange() {
    //triggered when location preset change
    let preset_location_element = document.getElementById("preset_location");
    let preset_location_value = preset_location_element.value;

    switch (preset_location_value) {
        case "NewYork":
            changeInputLatLng(40.76, -73.983, 15); //location from https://developers.google.com/maps/documentation/javascript/examples/aerial-simple
            break;
        case "LosAngeles":
            changeInputLatLng(33.958953, -118.243115, 15);
            break;
        case "Paris":
            changeInputLatLng(48.904503, 2.406343, 18);
            break;
        case "Nancy":
            changeInputLatLng(48.704753, 6.131208, 17);
            break;
        default:
            console.log("Unknown location " + preset_location_value);
    }
    createMapBase()

    function changeInputLatLng(lat, lng, zoom) {
        document.getElementById("input_lat").value = lat.toString();
        document.getElementById("input_lng").value = lng.toString();
        if (zoom != undefined) {

            document.getElementById("input_zoom").value = zoom.toString();
        }
    }

}

function getMercatorTileNumberFromLocation() {
    let latitude = parseFloat(document.getElementById("input_lat").value);
    let longitude = parseFloat(document.getElementById("input_lng").value);
    let zoom = parseFloat(document.getElementById("input_zoom").value);

    let tile_y = lat2tile(latitude, zoom);
    let tile_x = lng2tile(longitude, zoom);

    let return_tile_number = new Object;
    return_tile_number.x = tile_x;
    return_tile_number.y = tile_y;
    return_tile_number.z = zoom;
    return return_tile_number;
}

function getLocationFromMercatorTileNumber(tile_x, tile_y, zoom) {

    let longitude = tile2lng(tile_x, zoom);
    let latitude = tile2lat(tile_y, zoom);

    let return_location = new Object;
    return_location.lng = longitude;
    return_location.lat = latitude;
    return_location.z = zoom;
    return return_location;
}

//Lat Lng conversion from openstreetmap wiki
//https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#ECMAScript_(JavaScript/ActionScript,_etc.)

function lng2tile(lon, zoom) {
    return (Math.floor((lon + 180) / 360 * Math.pow(2, zoom)));
}

function lat2tile(lat, zoom) {
    return (Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)));
}

function tile2lng(x, z) {
    return (x / Math.pow(2, z) * 360 - 180);
}

function tile2lat(y, z) {
    var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
    return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
}

createMapBase();```
<pre class="snippet-code-css lang-css prettyprint-override"><code>* {
box-sizing: border-box;
}

label,
img {
user-select: none;
}

div,
body {
margin: 0;
padding: 0;
}

body {
margin: 5px;
font-family: sans-serif;
}

h1,
p {
margin: 0;
padding: 5px;
}

.map {
width: 100%;
height: 80vh;
background-color: gray;
position: relative;
overflow: hidden;
margin-top: 5px;
}

.map_container {
width: 100%;
height: 100%;
background-color: darkgrey;
}

.map_container img {
outline: 0.5px solid black;
aspect-ratio: 1/1;
}

select {
width: 35%;
}</code>```

Reproduce and compute 45 degrees tiles like google does

See https://developers.google.com/maps/documentation/javascript/examples/aerial-simple

  <input type="text" name="latitude" placeholder="latitude" value="40.76" id="input_lat">
  <input type="text" name="longitude" placeholder="longitude" value="-73.983" id="input_lng">
  <input type="text" name="zoom" placeholder="zoom" value="15" id="input_zoom">
  <input type="button" name="update_tiles" onclick="createMapBase()" value="Update layout">
  <input type="checkbox" name="is_oblique_view_visible" checked value="Is oblique view visible" id="is_oblique_view_visible" onchange="obliqueChangeVisibility()">Is oblique view visible

  Location preset :
  <select name="preset_location" id="preset_location" onchange="locationPresetChange()">
  <option value="NewYork">New York (États-Unis)</option>
  <option value="LosAngeles">Los Angeles (États-Unis)</option>
  <option value="Paris">Paris (France)</option>
  <option value="Nancy">Nancy (France)</option>
  </select>

```

I tried a lot of things like changing the anchoring of the coordinates (top left corner, bottom right corner, middle...) but nothing changed and I may know why.
I think google maps computes the coordinates of the tile in the middle of the screen and for the next tile, increments up or decrements down the coordinates of the row.
When the satellite display is toggled again, it recalculates the Mercator coordinates and displays the corresponding tile(s).

Do you think there is a way to fix the misplaced rows of tiles without using the way mentioned above?

Body:
I would like to replicate the 45 degree tilted view from the google maps javascript API.
For exemple, see this page from the google maps documentation : https://developers.google.com/maps/documentation/javascript/examples/aerial-simple

To do that i have backwards engineered the API to get the formulas that convert latitude and longitude coordinates into tile coordinates.

However, when I apply this formula, I get some misplaced rows of tiles.

//This code compute tiles numbers for 45 deg

function main(args) {
    //https://khms1.googleapis.com/kh?v=150&hl=fr&deg=0&x=41981&y=103113&z=18
    let longx = parseFloat(args.lng);
    let latx = parseFloat(args.lat);

    let ob1 = getLocation(latx, longx, args.z);
    let returnObject = new Object;
    returnObject.x = ob1.oa.toString();
    returnObject.y = ob1.pa.toString();
    returnObject.z = ob1.ya.toString();
    return returnObject;
}

function getLocation(lat, lng, zoom) {
    //this function from location return 45 deg tile number
    const degresinclinaison = 45;
    const heading = 0;
    const tileSize = 256;

    const powTwoZoomLevel = Math.pow(2, zoom);
    //compute the location to point
    let point = fromLatLngToPoint(lat, lng);
    let tileLocation = pointToTileNumber(point.x, point.y);
    return tileLocation;

    function fromLatLngToPoint(lat_args, lng_args) {
        //extract from the google api, i dont now what each variable is
        let h = 256 / 360; //0.711111111111111
        let a = Math.sin((lat_args * Math.PI / 180));
        let c = tileSize / (2 * Math.PI);

        let x = 128 + lng_args * h;
        let y = 128 + 0.5 * Math.log((1 + a) / (1 - a)) * -c;

        let returnObject = new Object;
        returnObject.x = x;
        returnObject.y = y;
        return returnObject;
    }

    function fromPointToLatLng(x_args, y_args) {
        //extract from the google api
        let c = tileSize / (2 * Math.PI);
        let h = 256 / 360; //0.711111111111111

        let lat = (180 * (2 * Math.atan(Math.exp((y_args - 128) / -c)) - Math.PI / 2) / Math.PI);
        let lng = (x_args - 128) / h;
        let returnObject = new Object;
        returnObject.lat = lat;
        returnObject.lng = lng;
        return returnObject;
    }

    function pointToTileNumber(x_args, y_args) {
        //this function convert the point to tilenumber
        let axeRotate = rotate(1, x_args, y_args);
        let x2 = axeRotate.X;
        let y2 = axeRotate.Y;
        //variable name is the same in the api. this is more simple to use them to.
        let h = Math.cos(degresinclinaison / 180 * Math.PI);
        var oa = Math.floor(x2 * powTwoZoomLevel / tileSize);
        var pa = Math.floor(powTwoZoomLevel * (.5 + (y2 / tileSize - .5) * h));
        var ya = zoom;

        return {
            oa: oa, //d(b.h * e / a.size.fa),
            pa: pa, //d(e * (.5 + (b.j / a.size.ha - .5) * a.h)),
            ya: ya //c
        }
    }

    function rotate(nbr, x1, y1) {
        //extract from the api, not working actually......
        let axeX = x1 //b.h;
        let axeY = y1 //b.j;
        switch ((360 + heading * nbr) % 360) {
            case 90:
                axeX = y1;
                axeY = tileSize - x1;
                break;
            case 180:
                axeX = tileSize - x1;
                axeY = tileSize - y1;
                break;
            case 270:
                axeX = tileSize - y1;
                axeY = x1
        }

        let returnObject = new Object;
        returnObject.X = axeX;
        returnObject.Y = axeY;
        return returnObject
    };
}

//This code show tiles on the html

let maptype = new Object;
maptype.satelite = new Object;
maptype.satelite.element = document.querySelector(".map_container .satelite");
maptype.satelite.url = "https://khms1.googleapis.com/kh?v=937&hl=fr&x={x}&y={y}&z={z}";

maptype.oblique = new Object;
maptype.oblique.element = document.querySelector(".map_container .oblique");
maptype.oblique.url = "https://khms1.googleapis.com/kh?v=150&hl=fr&deg=0&x={x}&y={y}&z={z}"

function createMapBase() {
    let view_tile_size = 30; //tile size of each tiles
    let map_container = document.querySelector(".map_container");
    let nbr_tiles_columns = Math.ceil(map_container.getBoundingClientRect().width / view_tile_size);
    let nbr_tiles_rows = Math.ceil(map_container.getBoundingClientRect().height / view_tile_size);
    createImgArray("satelite");
    createImgArray("oblique");

    //function createImgArray : load a array of img element into a container and load the url
    function createImgArray(type) {
        for (let tiles_rows = 0; tiles_rows < nbr_tiles_rows; tiles_rows++) {
            for (let tiles_columns = 0; tiles_columns < nbr_tiles_columns; tiles_columns++) {
                var img_element = document.createElement("img");
                if (type == "satelite") {
                    img_element.setAttribute("src", getMercatorUrl(maptype[type].url, tiles_rows, tiles_columns));
                } else if (type == "oblique") {
                    img_element.setAttribute("src", getObliqueUrl(maptype[type].url, tiles_rows, tiles_columns));
                } else {
                    console.warn("Error, this maptype is not supported : " + type);
                }

                img_element.style = "position : absolute; top:" + tiles_rows * view_tile_size + "px; left:" + tiles_columns * view_tile_size + "px; width:" + view_tile_size + "px";

                maptype[type].element.appendChild(img_element);
            }
        }
    }

}

function getMercatorUrl(base_url, row, column) {
    //get the mercator tile number -> the top-right tile
    let tiles_number = getMercatorTileNumberFromLocation();
    //generate the src url
    let final_url = base_url;
    final_url = final_url.replaceAll("{x}", tiles_number.x + column);
    final_url = final_url.replaceAll("{y}", tiles_number.y + row);
    final_url = final_url.replaceAll("{z}", tiles_number.z);
    return final_url;
}

function getObliqueUrl(base_url, row, column) {
    //get the mercator tile number -> the top-right tile
    let first_tile_number = getMercatorTileNumberFromLocation();
    //increment and get back the top-right location of the tile
    let converted_location = getLocationFromMercatorTileNumber(first_tile_number.x + column, first_tile_number.y + row, first_tile_number.z);
    //convert the location to 45 deg tiles number
    let tiles_number = main(converted_location);
    //generate the src url
    let final_url = base_url;
    final_url = final_url.replaceAll("{x}", tiles_number.x);
    final_url = final_url.replaceAll("{y}", tiles_number.y);
    final_url = final_url.replaceAll("{z}", tiles_number.z);
    return final_url;

}

function obliqueChangeVisibility() {
    //triggered when check checkbox
    if (document.getElementById("is_oblique_view_visible").checked) {
        maptype.oblique.element.style.visibility = "visible";
    } else {
        maptype.oblique.element.style.visibility = "hidden";
    }
}

function locationPresetChange() {
    //triggered when location preset change
    let preset_location_element = document.getElementById("preset_location");
    let preset_location_value = preset_location_element.value;

    switch (preset_location_value) {
        case "NewYork":
            changeInputLatLng(40.76, -73.983, 15); //location from https://developers.google.com/maps/documentation/javascript/examples/aerial-simple
            break;
        case "LosAngeles":
            changeInputLatLng(33.958953, -118.243115, 15);
            break;
        case "Paris":
            changeInputLatLng(48.904503, 2.406343, 18);
            break;
        case "Nancy":
            changeInputLatLng(48.704753, 6.131208, 17);
            break;
        default:
            console.log("Unknown location " + preset_location_value);
    }
    createMapBase()

    function changeInputLatLng(lat, lng, zoom) {
        document.getElementById("input_lat").value = lat.toString();
        document.getElementById("input_lng").value = lng.toString();
        if (zoom != undefined) {

            document.getElementById("input_zoom").value = zoom.toString();
        }
    }

}

function getMercatorTileNumberFromLocation() {
    let latitude = parseFloat(document.getElementById("input_lat").value);
    let longitude = parseFloat(document.getElementById("input_lng").value);
    let zoom = parseFloat(document.getElementById("input_zoom").value);

    let tile_y = lat2tile(latitude, zoom);
    let tile_x = lng2tile(longitude, zoom);

    let return_tile_number = new Object;
    return_tile_number.x = tile_x;
    return_tile_number.y = tile_y;
    return_tile_number.z = zoom;
    return return_tile_number;
}

function getLocationFromMercatorTileNumber(tile_x, tile_y, zoom) {

    let longitude = tile2lng(tile_x, zoom);
    let latitude = tile2lat(tile_y, zoom);

    let return_location = new Object;
    return_location.lng = longitude;
    return_location.lat = latitude;
    return_location.z = zoom;
    return return_location;
}

//Lat Lng conversion from openstreetmap wiki
//https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#ECMAScript_(JavaScript/ActionScript,_etc.)

function lng2tile(lon, zoom) {
    return (Math.floor((lon + 180) / 360 * Math.pow(2, zoom)));
}

function lat2tile(lat, zoom) {
    return (Math.floor((1 - Math.log(Math.tan(lat * Math.PI / 180) + 1 / Math.cos(lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, zoom)));
}

function tile2lng(x, z) {
    return (x / Math.pow(2, z) * 360 - 180);
}

function tile2lat(y, z) {
    var n = Math.PI - 2 * Math.PI * y / Math.pow(2, z);
    return (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
}

createMapBase();

* {
box-sizing: border-box;
}

label,
img {
user-select: none;
}

div,
body {
margin: 0;
padding: 0;
}

body {
margin: 5px;
font-family: sans-serif;
}

h1,
p {
margin: 0;
padding: 5px;
}

.map {
width: 100%;
height: 80vh;
background-color: gray;
position: relative;
overflow: hidden;
margin-top: 5px;
}

.map_container {
width: 100%;
height: 100%;
background-color: darkgrey;
}

.map_container img {
outline: 0.5px solid black;
aspect-ratio: 1/1;
}

select {
width: 35%;
}

Reproduce and compute 45 degrees tiles like google does

See https://developers.google.com/maps/documentation/javascript/examples/aerial-simple

  <input type="text" name="latitude" placeholder="latitude" value="40.76" id="input_lat">
  <input type="text" name="longitude" placeholder="longitude" value="-73.983" id="input_lng">
  <input type="text" name="zoom" placeholder="zoom" value="15" id="input_zoom">
  <input type="button" name="update_tiles" onclick="createMapBase()" value="Update layout">
  <input type="checkbox" name="is_oblique_view_visible" checked value="Is oblique view visible" id="is_oblique_view_visible" onchange="obliqueChangeVisibility()">Is oblique view visible

  Location preset :
  <select name="preset_location" id="preset_location" onchange="locationPresetChange()">
  <option value="NewYork">New York (États-Unis)</option>
  <option value="LosAngeles">Los Angeles (États-Unis)</option>
  <option value="Paris">Paris (France)</option>
  <option value="Nancy">Nancy (France)</option>
  </select>

I tried a lot of things like changing the anchoring of the coordinates (top left corner, bottom right corner, middle...) but nothing changed and I may know why.
I think google maps computes the coordinates of the tile in the middle of the screen and for the next tile, increments up or decrements down the coordinates of the row.
When the satellite display is toggled again, it recalculates the Mercator coordinates and displays the corresponding tile(s).

Do you think there is a way to fix the misplaced rows of tiles without using the way mentioned above?


问:
Fetching sessions saga refactor to RXJS epic
trying to refactor the saga code into rxjs epic. It's fetching sessions from the server

```<code> yield race([
      call(fetchSessions, sessionsList), //complete retrieving sessions
      call(sessionWatchdog, 20000), //or timeout with 20 seconds of inactivity
    ]);

function* fetchSessions(list: Array<number>): Generator<*, *, *> {
  console.log('FETCH ALL', list.length);
  for (let id of list) {
    yield fork(fetchSession, id);
  }
}
function* sessionWatchdog(duration: number): Generator<*, *, *> {
  while (true) {
    let { retrieved, timeout } = yield race({
      retrieved: take('SESSION_RETRIEVED'),
      timeout: delay(duration),
    });
    if (timeout) {
      return 'TIMEOUT';
    }
  }
}

</code>```

The fetch session is an async function that retrieves a single session. I'm not sure how to make sure to make an equivalent epic. After each session is fetched need to make sure it was retrieved or timeout and handle that.

That's what I have now, but don't understand how to make it do the same as saga code with sessionWatchdog

```<code>export const fetch_all_sessions = (
  action$: Obs<*>,
  state$: typeof StateObservable
): Obs<*> =>
  action$.pipe(
    filter(action => action.type === 'FETCH_ALL_SESSIONS'),
    switchMap(action => {
      let list = action.list;
      from(list).pipe(
        map(id => {
          return fetchSession(id);
        })
      );
      return of({ type: '' });
    })
  );

</code>```

Thanks for your help or advice

Body:
trying to refactor the saga code into rxjs epic. It's fetching sessions from the server

 yield race([
      call(fetchSessions, sessionsList), //complete retrieving sessions
      call(sessionWatchdog, 20000), //or timeout with 20 seconds of inactivity
    ]);

function* fetchSessions(list: Array<number>): Generator<*, *, *> {
  console.log('FETCH ALL', list.length);
  for (let id of list) {
    yield fork(fetchSession, id);
  }
}
function* sessionWatchdog(duration: number): Generator<*, *, *> {
  while (true) {
    let { retrieved, timeout } = yield race({
      retrieved: take('SESSION_RETRIEVED'),
      timeout: delay(duration),
    });
    if (timeout) {
      return 'TIMEOUT';
    }
  }
}

The fetch session is an async function that retrieves a single session. I'm not sure how to make sure to make an equivalent epic. After each session is fetched need to make sure it was retrieved or timeout and handle that.

That's what I have now, but don't understand how to make it do the same as saga code with sessionWatchdog

export const fetch_all_sessions = (
  action$: Obs<*>,
  state$: typeof StateObservable
): Obs<*> =>
  action$.pipe(
    filter(action => action.type === 'FETCH_ALL_SESSIONS'),
    switchMap(action => {
      let list = action.list;
      from(list).pipe(
        map(id => {
          return fetchSession(id);
        })
      );
      return of({ type: '' });
    })
  );

Thanks for your help or advice