xionghao-hw opened a new issue #9024:
URL: https://github.com/apache/shardingsphere/issues/9024


   ## Bug Report
   
   **For English only**, other languages will not accept.
   
   Before report a bug, make sure you have:
   
   - Searched open and closed [GitHub 
issues](https://github.com/apache/shardingsphere/issues).
   - Read documentation: [ShardingSphere 
Doc](https://shardingsphere.apache.org/document/current/en/overview).
   
   Please pay attention on issues you submitted, because we maybe need more 
details. 
   If no response anymore and we cannot reproduce it on current information, we 
will **close it**.
   
   Please answer these questions before submitting your issue. Thanks!
   
   ### Which version of ShardingSphere did you use?
   5.0.0-alpha
   
   ### Which project did you use? ShardingSphere-JDBC or ShardingSphere-Proxy?
   ShardingSphere-Proxy
   
   ### Steps to reproduce the behavior, such as: SQL to execute, sharding rule 
configuration, when exception occur etc.
   Use the vertical sharding solution,different table on defferent database 
instance, config-sharding.yaml like this:
   ```
   dataSources:
     ds_0:
       url: jdbc:postgresql://*****:5432/****
       username: ****
       password: ****
       connectionTimeoutMilliseconds: 30000
       idleTimeoutMilliseconds: 60000
       maxLifetimeMilliseconds: 1800000
       maxPoolSize: 50
       minPoolSize: 1
       maintenanceIntervalMilliseconds: 30000
   #rules:
   # !SHARDING
   # tables:
   ```
   not config any sharding rules, expected the proxy can scan all table 
infomation.
   
   And then ,i send a sql like this:
   ```sql
   SELECT
       sub_ports.id AS id,
       sub_ports.name AS name,
       sub_ports.admin_state_up AS admin_state_up,
       sub_ports.status AS status,
       sub_ports.network_id AS network_id,
       sub_ports.tenant_id AS tenant_id,
       sub_ports.tenant_id AS project_id,
       sub_ports.device_id AS device_id,
       sub_ports.mac_address AS mac_address,
       sub_ports.device_owner AS device_owner,
       qos_port_policy_bindings.policy_id AS qos_policy_id,
       sub_ports.description AS description,
       sub_ports.created_at AS created_at,
       sub_ports.updated_at AS updated_at,
       ml2_port_bindings.vnic_type AS binding_vnic_type,
       ml2_port_bindings.vif_details AS binding_vif_details,
       ml2_port_bindings.profile AS binding_profile,
       sub_ports.instance_id AS instance_id,
       sub_ports.instance_type AS instance_type,
       sub_ports.ecs_flavor AS ecs_flavor
   FROM
       (
           SELECT
               ports.id AS id,
               ports.name AS name,
               ports.admin_state_up AS admin_state_up,
               ports.status AS status,
               ports.network_id AS network_id,
               ports.tenant_id AS tenant_id,
               ports.device_id AS device_id,
               ports.mac_address AS mac_address,
               ports.device_owner AS device_owner,
               ports.description AS description,
               ports.created_at AS created_at,
               ports.updated_at AS updated_at,
               ports.instance_id AS instance_id,
               ports.instance_type AS instance_type,
               ports.ecs_flavor AS ecs_flavor
           FROM
               ports
           WHERE
                        ports.tenant_id IN('xxxxxxxxxxxxxxxxxx')
           ORDER BY
               ports.id ASC LIMIT 2000
       ) AS sub_ports LEFT JOIN ml2_port_bindings
           ON ml2_port_bindings.port_id = sub_ports.id LEFT JOIN 
qos_port_policy_bindings
           ON qos_port_policy_bindings.port_id = sub_ports.id LEFT JOIN 
portsecuritybindings
           ON portsecuritybindings.port_id = sub_ports.id 
   ORDER BY
       sub_ports.id ASC
   ```
   Table ports、ml2_port_bindings、qos_port_policy_bindings、portsecuritybindings 
all in ds_0
   I expect this sql can router to ds_0, but not.
   ### Actual behavior
   The sharding proxy threw an exception .
   ```
   [ERROR] 15:28:28.331 [pool-4-thread-1] o.a.s.p.f.c.CommandExecutorTask - 
Exception occur:
   java.lang.IllegalStateException: Can not find owner from table.
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.find(ProjectionsContextEngine.java:198)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.findShorthandProjection(ProjectionsContextEngine.java:139)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.containsItemWithOwnerInShorthandProjections(ProjectionsContextEngine.java:135)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.containsItemInShorthandProjection(ProjectionsContextEngine.java:121)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.containsProjection(ProjectionsContextEngine.java:105)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.getDerivedOrderColumns(ProjectionsContextEngine.java:96)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.getDerivedOrderByColumns(ProjectionsContextEngine.java:88)
           at 
org.apache.shardingsphere.infra.binder.segment.select.projection.engine.ProjectionsContextEngine.createProjectionsContext(ProjectionsContextEngine.java:71)
           at 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext.<init>(SelectStatementContext.java:89)
           at 
org.apache.shardingsphere.infra.binder.SQLStatementContextFactory.getDMLStatementContext(SQLStatementContextFactory.java:113)
           at 
org.apache.shardingsphere.infra.binder.SQLStatementContextFactory.newInstance(SQLStatementContextFactory.java:97)
           at 
org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngineFactory.createLogicSQL(DatabaseCommunicationEngineFactory.java:88)
           at 
org.apache.shardingsphere.proxy.backend.communication.DatabaseCommunicationEngineFactory.newBinaryProtocolInstance(DatabaseCommunicationEngineFactory.java:80)
           at 
org.apache.shardingsphere.proxy.frontend.postgresql.command.query.binary.bind.PostgreSQLComBindExecutor.<init>(PostgreSQLComBindExecutor.java:78)
           at 
org.apache.shardingsphere.proxy.frontend.postgresql.command.PostgreSQLCommandExecutorFactory.newInstance(PostgreSQLCommandExecutorFactory.java:62)
           at 
org.apache.shardingsphere.proxy.frontend.postgresql.command.PostgreSQLCommandExecuteEngine.getCommandExecutor(PostgreSQLCommandExecuteEngine.java:61)
           at 
org.apache.shardingsphere.proxy.frontend.command.CommandExecutorTask.executeCommand(CommandExecutorTask.java:99)
           at 
org.apache.shardingsphere.proxy.frontend.command.CommandExecutorTask.run(CommandExecutorTask.java:76)
           at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
           at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
           at java.lang.Thread.run(Thread.java:748)
   ```
   
   ### Reason analyze (If you can)
   I debuged the code, I found that the alias of the subquery is not processed 
in ProjectionsContentEngine. The alias of subquery is processed as a normal 
table name.
   ```java
       // tableNameOrAlias = "sub_ports" is not is not included in tables, and 
then throw Exception
       private SimpleTableSegment find(final String tableNameOrAlias, final 
Collection<SimpleTableSegment> tables) {
           for (SimpleTableSegment each : tables) {
               if 
(tableNameOrAlias.equalsIgnoreCase(each.getTableName().getIdentifier().getValue())
 || tableNameOrAlias.equals(each.getAlias().orElse(null))) {
                   return each;
               }
           }
           throw new IllegalStateException("Can not find owner from table.");
       }
   ```
   So I try to modify sql like this:
   ```sql
   SELECT
   *
   FROM
       (
           SELECT
               ports.id AS id,
               ports.name AS name,
               ports.admin_state_up AS admin_state_up,
               ports.status AS status,
               ports.network_id AS network_id,
               ports.tenant_id AS tenant_id,
               ports.device_id AS device_id,
               ports.mac_address AS mac_address,
               ports.device_owner AS device_owner,
               ports.description AS description,
               ports.created_at AS created_at,
               ports.updated_at AS updated_at,
               ports.instance_id AS instance_id,
               ports.instance_type AS instance_type,
               ports.ecs_flavor AS ecs_flavor
           FROM
               ports
           WHERE
                        ports.tenant_id IN('acea140a0ad54e6f98a8befdc2dab472')
           ORDER BY
               ports.id ASC LIMIT 2000
       ) AS sub_ports LEFT JOIN ml2_port_bindings
           ON ml2_port_bindings.port_id = sub_ports.id LEFT JOIN 
qos_port_policy_bindings
           ON qos_port_policy_bindings.port_id = sub_ports.id LEFT JOIN 
portsecuritybindings
           ON portsecuritybindings.port_id = sub_ports.id 
   ORDER BY
       sub_ports.id ASC
   ```
   Although it can work, it is not applicable to business scenarios.
   
   So i think maybe we can get the subquery alias before this handle 
projections.
   
   ```java
       public SelectStatementContext(final PhysicalSchemaMetaData 
schemaMetaData, final List<Object> parameters, final SelectStatement 
sqlStatement) {
           super(sqlStatement);
           tablesContext = new TablesContext(getSimpleTableSegments());
           groupByContext = new 
GroupByContextEngine().createGroupByContext(sqlStatement);
           orderByContext = new 
OrderByContextEngine().createOrderBy(sqlStatement, groupByContext);
           // Get the subquery alias before this handle projections
           projectionsContext = new 
ProjectionsContextEngine(schemaMetaData).createProjectionsContext(getSimpleTableSegments(),
 getSqlStatement().getProjections(), groupByContext, orderByContext);
           paginationContext = new 
PaginationContextEngine().createPaginationContext(sqlStatement, 
projectionsContext, parameters);
           containsSubquery = containsSubquery();
       }
   ```
   
   
   ### Example codes for reproduce this issue (such as a github link).
   None.


----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to