Hi Haisheng,

I double-checked the code. My original version returned false for some
cases, but it didn't affect number of rules calls anyway, so I changed it
to always return true. Please note that if I change the code as you
suggested, the test started failing, because bottom-up propagation of rule
calls no longer work: when the child is converted to physical form, the
parent logical node is not notified. This is the very problem I address
with that weird physical-to-logical conversions: they do not make sense,
and converter expansion does not produce any new rels, but their existence
allow for logical rule re-trigger which ultimately allow the plan to
compile.

Regarding two conventions - I agree that it may look strange, but I do not
see any problems from the correctness perspective. Separation of logical
and physical planning helps me avoid excessive expansion of the search
place: I do not want my physical rules to produce new rels from not
optimized logical rels. Do you see any problems with that approach?

Regards,
Vladimir

ср, 6 нояб. 2019 г. в 03:52, Haisheng Yuan <h.y...@alibaba-inc.com>:

> Hi Vladimir,
>
> The code in PHYSICAL convention L44 looks weird, I think it always returns
> true.
>
> https://github.com/devozerov/calcite-optimizer/blob/master/src/main/java/devozerov/HazelcastConventions.java#L44
>
> Try this:
>
> fromTraits.containsIfApplicable(Convention.PHYSICAL)
>     && toTraits.containsIfApplicable(Convention.PHYSICAL);
>
>
> Adding a AbstractConverter on logical operators is meaningless. Calcite is
> mixing the concept of logical and physical together, which is sad.
>
> BTW, using 2 conventions is not appropriate and wrong.
>
> - Haisheng
>
> ------------------------------------------------------------------
> 发件人:Vladimir Ozerov<ppoze...@gmail.com>
> 日 期:2019年11月05日 18:02:15
> 收件人:Haisheng Yuan<h.y...@alibaba-inc.com>
> 抄 送:dev@calcite.apache.org (dev@calcite.apache.org)<dev@calcite.apache.org
> >
> 主 题:Re: Re: Problem with converters and possibly rule matching
>
> Hi Haisheng,
>
>  think I already tried something very similar to what you explained, but
> it gave not an optimal plan. Please let me describe what I did. I would
> appreciate your feedback.
>
> 1) We start with a simple operator tree Root <- Project <- Scan, where
> the root is a final aggregator in the distributed query engine:
> -> LogicalRoot
>  -> LogicalProject
>   -> LogicalScan
>
> 2) First, we convert the Root and enforce SINGLETON distribution on a
> child:
> *-> PhysicalRoot[SINGLETON]*
> * -> Enforcer#1[SINGLETON]*
>   -> LogicalProject
>    -> LogicalScan
>
> 3) Then the project's rule is invoked. It doesn't know the distribution of
> the input, so it requests ANY distribution. Note that we have to set ANY to
> the project as well since we do not know the distribution of the input:
> -> PhysicalRoot[SINGLETON]
>  -> Enforcer#1[SINGLETON]
> *  -> PhysicalProject[ANY]*
> *   -> Enforcer#2[ANY]*
>     -> LogicalScan
>
> 4) Finally, the physical scan is created and its distribution is resolved.
> Suppose that it is REPLICATED, i.e. the whole result set is located on all
> nodes.
> -> PhysicalRoot[SINGLETON]
>  -> Enforcer#1[SINGLETON]
>   -> PhysicalProject[ANY]
>    -> Enforcer#2[ANY]
> *    -> PhysicalScan[REPLICATED]*
>
> 5) Now as all logical nodes are converted, we start resolving enforcers.
> The second one is no-op, since REPLICATED satisfies ANY:
> -> PhysicalRoot[SINGLETON]
>  -> Enforcer#1[SINGLETON]
>   -> PhysicalProject[ANY]
>    -> PhysicalScan[REPLICATED]
>
> 6) But the first enforcer now requires an Exchange, since ANY doesn't
> satisfy SINGLETON!
> -> PhysicalRoot[SINGLETON]
> * -> SingletonExchange[SINGLETON]*
>   -> PhysicalProject[ANY] // <= unresolved!
>    -> PhysicalScan[REPLICATED]
>
> The resulting plan requires data movement only because we didn't know
> precise distribution of the PhysicalProject when it was created. But should
> I enable Convention.Impl.canConvertConvention, bottom-up propagation
> kicks in, and the correct plan is produced because now LogicalProject has
> a chance to be converted to PhysicalProject with the concrete
> distribution. The optimized plan looks like this (since REPLICATED
> satisfies SINGLETON):
> -> PhysicalRoot[SINGLETON]
>  -> PhysicalProject[REPLICATED]
>   -> PhysicalScan[REPLICATED]
>
> You may see this in action in my reproducer:
> 1) Test producing "bad" plan:
> https://github.com/devozerov/calcite-optimizer/blob/master/src/test/java/devozerov/OptimizerTest.java#L45
> 2) Root enforces SINGLETON on Project:
> https://github.com/devozerov/calcite-optimizer/blob/master/src/main/java/devozerov/physical/RootPhysicalRule.java#L45
> 3) Project enforces default (ANY) distribution on Scan:
> https://github.com/devozerov/calcite-optimizer/blob/master/src/main/java/devozerov/physical/ProjectPhysicalRule.java#L49
>
> Please let me know if this flow is similar to what you meant.
>
> Regards,
> Vladimir.
>
> пн, 4 нояб. 2019 г. в 10:33, Haisheng Yuan <h.y...@alibaba-inc.com>:
>
>> Hi Vladimir,
>>
>> This is still can be done through top-down request approach.
>>
>> PhysicalFilter operator should request ANY distribution from child
>> operator, unless there is outer reference in the filter condition, in which
>> case, PhysicalFilter should request SINGLETON or BROADCAST distribution. So
>> in your case, PhysicalFilter request ANY, its required distribution will be
>> enforced on filter's output.
>>
>> Regarding index usage, you should have a FIlterTableScan2IndexGet logical
>> transformation rule, and a IndexGet2IndexScan physical implementation rule.
>> Note that IndexGet is a logical operator and IndexScan is a physical
>> operator, which are also used by SQL Server.
>>
>> - Haisheng
>>
>> ------------------------------------------------------------------
>> 发件人:Vladimir Ozerov<ppoze...@gmail.com>
>> 日 期:2019年11月01日 17:30:26
>> 收件人:<dev@calcite.apache.org>
>> 主 题:Re: Problem with converters and possibly rule matching
>>
>> Hi Stamatis,
>>
>> Thank you for your reply. I also thought that we may set the distribution
>> trait during logical planning because it is known in advance. And the
>> example I gave will work! :-) But unfortunately, it will work only because
>> the tree is very simple, and the Project is adjacent to the Scan. This is
>> how my reproducer will work in that case:
>> 1) Root: enforce "SINGLETON" on Project
>> 2) Project: check the logical Scan, infer already resolved distribution,
>> then convert to [PhyiscalProject <- PhysicalScan]
>> 3) Resolve Root enforcer, adding and Exchange if needed.
>>
>> But this stops working as soon as a plan becomes more complex so that it
>> is
>> impossible to infer the distribution from the child immediately. E.g.:
>> LogicalRoot [distribution=SINGLETON]
>> -> LogicalProject // We are here new and cannot produce the physical
>> project
>> -> LogicalFilter[distribution=?]
>> -> LogicalScan[distribution=REPLICATED]
>>
>> This is where your suggestion with cascading enforcement may kick in. But
>> now consider that instead of having REPLICATED distribution, which
>> satisfies SINGLETON, we have a PARTITIONED distribution, It doesn't
>> satisfy
>> SINGLETON, so we have to insert the exchange.
>>
>> Before:
>> PhysicalRoot [SINGLETON]
>> -> PhysicalProject [SINGLETON]
>> -> PhysicalFilter [SINGLETON]
>> -> LogicalScan [PARTITIONED] // SINGLETON is enforced here
>>
>> After:
>> PhysicalRoot [SINGLETON]
>> -> PhysicalProject [SINGLETON]
>> -> PhysicalFilter [SINGLETON]
>> -> SingletonExchange [SINGLETON]
>> -> PhysicalScan [PARTITIONED]
>>
>> But unfortunately, this plan is not optimal. Since we perform Project and
>> Filter after the exchange, we now have to reshuffle the whole table. The
>> optimal plan would be to pushdown Project and Filter past exchange:
>> PhysicalRoot [SINGLETON]
>> -> SingletonExchange [SINGLETON]
>> -> PhysicalProject [PARTITIONED]
>> -> PhysicalFilter [PARTITIONED]
>> -> PhysicalScan [PARTITIONED]
>>
>> But in order to achieve that, now I need to introduce new rules which will
>> attempt to transpose dozens of different operators past exchange, so most
>> likely the planning will never finish :-)
>>
>> This is why it seems that the bottom-up approach seems to be more natural
>> for such cases. Another example is index support. A table may have a
>> number
>> of access methods in addition to plain scan, and every such method may
>> produce a physical scan with different collations. It is not practical to
>> try to enforce something from the top. Instead, we'd better produce
>> alternatives from the bottom.
>>
>> Basically, Drill tries to mix two approaches. First, it tries to derive
>> traits from the child. If it fails and no transformations were created, it
>> just stops trait propagation. As a result, an exchange is created on top
>> of
>> the operator where we stopped, which again leads to not optimal plans. You
>> may observe this in action if you run my reproducer. "testPass" produces
>> an
>> optimal plan with help of abstract converters. "testDrill" produces not
>> optimal plan with the unnecessary exchange.
>>
>> All in all, I cannot get how we can employ distribution metadata and index
>> metadata for optimal planning without using a pure bottom-up approach.
>>
>> Regards,
>> Vladimir.
>>
>> пт, 1 нояб. 2019 г. в 11:42, Stamatis Zampetakis <zabe...@gmail.com>:
>>
>> > The discussion is interesting thanks for the nice examples.
>> > I am replying in this thread since it has all the examples and the
>> history
>> > of the conversation.
>> >
>> > *Part I: Distribution physical or logical property*
>> >
>> > The Volcano paper writes the following regarding properties:
>> >
>> > "Logical properties can be derived from the logical algebra expression
>> and
>> > include schema, expected size, etc., while physical properties depend on
>> > algorithms, e.g., sort order, partitioning, etc."
>> >
>> > We could say that partitioning is not only a property which depends on
>> an
>> > algorithm but a property which depends on the schema. When you have a
>> table
>> > you know in advance that the particular table is replicated.
>> >
>> > Basically, this means that the starting "logical" plan in your case
>> could
>> > be the following:
>> > RootLogicalRel[convention=LOGICAL, distribution=ANY]
>> > -> ProjectLogicalRel[convention=LOGICAL, distribution=ANY]
>> > -> MapScanLogicalRel[convention=LOGICAL, distribution=REPLICATED]
>> >
>> > When you are about to create your physical projection it is not
>> necessary
>> > to create three equivalent paths but the most promising by asking the
>> input
>> > what can it offer as traits. Again this partially overlaps with the
>> > discussion about "On demand traitset" [1] where as I wrote there is
>> already
>> > a mechanism to derive traits from children (collation, distribution,
>> etc.).
>> >
>> > Note that I am not saying that there is nothing more to be done to
>> improve
>> > the Calcite optimizer; I am just trying to provide a viable alternative
>> > given the current situation of the project.
>> >
>> > *Part II: Example with the original Volcano optimizer*
>> >
>> > Now let me try to show how the original (from the paper) Volcano
>> optimizer
>> > could handle your query.
>> >
>> > The optimization starts and we request two properties convention and
>> > distribution.
>> >
>> > RootLogicalRel[convention=PHYSICAL, distribution=SINGLETON]
>> > -> ProjectLogicalRel
>> > -> MapScanLogicalRel
>> >
>> > Rule 1: RootLogicalRel -> RootPhysicalRel applies the algorithm but
>> cannot
>> > satisfy the SINGLETON property so it propagates the demand
>> >
>> > RootPhysicalRel
>> > -> ProjectLogicalRel [convention=PHYSICAL, distribution=SINGLETON]
>> > -> MapScanLogicalRel
>> >
>> > Rule 2: ProjectLogicalRel -> ProjectPhysicalRel applies the algorithm
>> but
>> > cannot satisfy the SINGLETON property so it propagates the demand
>> >
>> > RootPhysicalRel
>> > -> ProjectPhysicalRel
>> > -> MapScanLogicalRel [convention=PHYSICAL, distribution=SINGLETON]
>> >
>> > Rule 3: MapScanLogicalRel -> MapScanPhysicalRel applies the algorithm
>> and
>> > given that the table is replicated it satisfies the distribution
>> property.
>> >
>> > RootPhysicalRel
>> > -> ProjectPhysicalRel
>> > -> MapScanPhysicalRel
>> >
>> > So we end up with a complete plan that satisfies all properties and does
>> > not have redundant exchange operators.
>> > Moreover we didn't require all possible distributions when we applied
>> Rule
>> > 2 since we just want to satisfy the SINGLETON property requested by the
>> > parent.
>> > The example above does not demonstrate the additional optimization paths
>> > which would be apply an enforcer (an Exchange operator to satisfy the
>> > SINGLETON property) at a higher level than the scan.
>> >
>> > Would this be an acceptable approach? Does it still suffer from a big
>> > search space?
>> >
>> > To make the analog with the actual Volcano optimizer in Calcite the
>> thing
>> > that may be missing is to be able to know what trait was requested by
>> the
>> > parent during the application of Rule 2.
>> >
>> > Best,
>> > Stamatis
>> >
>> > [1]
>> >
>> >
>> https://lists.apache.org/thread.html/79dac47ea50b5dfbd3f234e368ed61d247fb0eb989f87fe01aedaf25@%3Cdev.calcite.apache.org%3E
>> >
>> > On Wed, Oct 30, 2019 at 7:24 PM Vladimir Ozerov <ppoze...@gmail.com>
>> > wrote:
>> >
>> > > Hi Stamatis,
>> > >
>> > > The problem that the presented reproducer is a very simplified
>> version of
>> > > what is actually needed. In reality, there are several distribution
>> > types -
>> > > PARTITIONED, REPLICATED, SINGLETON. To make things worse, PARTITIONED
>> may
>> > > or may not have concrete distribution fields. In theory, I can create
>> one
>> > > transformation per distribution type, but that would increase plan
>> space
>> > > significantly. In my sample "Root <- Project <- Scan" plan, there is
>> no
>> > > room for optimization at all, we only need to convert the nodes and
>> > > propagate traits. But if I follow the proposed approach, the planner
>> > would
>> > > create three equivalent paths. For complex queries, this may increase
>> > > optimization time significantly.
>> > >
>> > > What I need instead is to gradually convert and optimize nodes
>> > *bottom-up*,
>> > > instead of top-bottom. That is, create a physical scan first, then
>> > create a
>> > > physical project on top of it, etc. But at the same time, some rules
>> > still
>> > > require the top-bottom approach. So essentially I need the optimizer
>> to
>> > do
>> > > both. Abstract converters help me establish bottom-up preparation but
>> do
>> > > this at the cost of considering too many trait pairs, and as a result,
>> > also
>> > > pollute the search space.
>> > >
>> > > To the contrast, precise command "I transformed the node A to node B,
>> > > please re-trigger the rules for A's parents" would allow us to
>> re-trigger
>> > > only required rules, without adding more nodes.
>> > >
>> > > Does it make sense?
>> > >
>> > > Regards,
>> > > Vladimir.
>> > >
>> > > ср, 30 окт. 2019 г. в 21:02, Stamatis Zampetakis <zabe...@gmail.com>:
>> > >
>> > > > I admit that I didn't thoroughly read the exchanges so far but
>> forcing
>> > > the
>> > > > rules trigger does not seem the right approach.
>> > > >
>> > > > Other than that I would like to backtrack a bit to point 4.3 raised
>> by
>> > > > Vladimir.
>> > > >
>> > > > "ProjectPhysicalRule [6] - transforms logical project to physical
>> > > > project *ONLY* if there is an underlying physical input with
>> REPLICATED
>> > > or
>> > > > SINGLETON distribution"
>> > > >
>> > > > The rule could be modified to do the following two transformations:
>> > > > 1. Create a physical project and require the input to be REPLICATED.
>> > > > 2. Create a physical project and require
>> > > > the input to be SINGLETON.
>> > > >
>> > > > I would assume that afterwards when your scan rule fires it should
>> go
>> > to
>> > > > the appropriate subset and give you back the desired plan. Is there
>> a
>> > > > problem with this approach?
>> > > >
>> > > > Best,
>> > > > Stamatis
>> > > >
>> > > > On Wed, Oct 30, 2019, 5:52 PM Seliverstov Igor <
>> gvvinbl...@gmail.com>
>> > > > wrote:
>> > > >
>> > > > > Unfortunately it requires package-private API usage.
>> > > > >
>> > > > > Best solution there if Calcite provide it for end users.
>> > > > >
>> > > > > ср, 30 окт. 2019 г., 18:48 Vladimir Ozerov <ppoze...@gmail.com>:
>> > > > >
>> > > > > > “e pension” == “expand conversion” :)
>> > > > > >
>> > > > > > ср, 30 окт. 2019 г. в 18:46, Vladimir Ozerov <
>> ppoze...@gmail.com>:
>> > > > > >
>> > > > > > > Yes, that may work. Even if e pension rule is used, for the
>> most
>> > > > cases
>> > > > > it
>> > > > > > > will not trigger any real conversions, since we are moving
>> from
>> > > > > abstract
>> > > > > > > convention to physical, and created converters will have the
>> > > opposite
>> > > > > > trait
>> > > > > > > direction (from physical to abstract).
>> > > > > > >
>> > > > > > > But again - ideally we only need to re-trigger the rules for a
>> > > > specific
>> > > > > > > node, no more than that. So API support like
>> > > > > > > “VolcanoPlanner.forceRules(RelNode)” would be very convenient.
>> > > > > > >
>> > > > > > > What do you think?
>> > > > > > >
>> > > > > > > ср, 30 окт. 2019 г. в 17:56, Seliverstov Igor <
>> > > gvvinbl...@gmail.com
>> > > > >:
>> > > > > > >
>> > > > > > >> I considered manual rules calling too, for now we use
>> abstract
>> > > > > > converters
>> > > > > > >> +
>> > > > > > >> ExpandConversionRule for exchanges producing.
>> > > > > > >>
>> > > > > > >> You may create such converters manually (checking appropriate
>> > > > subset)
>> > > > > > this
>> > > > > > >> case you may reduce created converters count, also, a
>> converter
>> > > is a
>> > > > > > quite
>> > > > > > >> special node, that does almost nothing (without corresponding
>> > > rule)
>> > > > it
>> > > > > > may
>> > > > > > >> be used just as a rule trigger.
>> > > > > > >>
>> > > > > > >> Regards,
>> > > > > > >> Igor
>> > > > > > >>
>> > > > > > >> ср, 30 окт. 2019 г., 17:31 Vladimir Ozerov <
>> ppoze...@gmail.com
>> > >:
>> > > > > > >>
>> > > > > > >> > One funny hack which helped me is manual registration of a
>> > fake
>> > > > > > RelNode
>> > > > > > >> > with desired traits through VolcanoPlanner.register()
>> method.
>> > > But
>> > > > > > again,
>> > > > > > >> > this leads to trashing. What could really help is a call to
>> > > > > > >> > VolcanoPlanner.fireRules() with desired rel. But this
>> doesn't
>> > > work
>> > > > > out
>> > > > > > >> of
>> > > > > > >> > the box since some internals of the rule queue needs to be
>> > > > adjusted.
>> > > > > > >> >
>> > > > > > >> > What does the community think about adding a method which
>> will
>> > > > > re-add
>> > > > > > >> rules
>> > > > > > >> > applicable to the specific RelNode to the rule queue?
>> > > > > > >> >
>> > > > > > >> > ср, 30 окт. 2019 г. в 17:00, Vladimir Ozerov <
>> > > ppoze...@gmail.com
>> > > > >:
>> > > > > > >> >
>> > > > > > >> > > Hi Igor,
>> > > > > > >> > >
>> > > > > > >> > > Yes, I came to the same conclusion, thank you. This is
>> how
>> > it
>> > > > > > >> basically
>> > > > > > >> > > happens when converters are disabled:
>> > > > > > >> > > 1) We start with initial tree: [LogicalProject] <-
>> > > [LogicalScan]
>> > > > > > >> > > 2) Then we convert LogicalScan to PhysicalScan, so it is
>> > added
>> > > > to
>> > > > > > the
>> > > > > > >> > > set: [LogicalProject] <- [LogicalScan, PhysicalScan]
>> > > > > > >> > > 3) Finally, when it is time to fire a rule for
>> PhysicalScan,
>> > > we
>> > > > > try
>> > > > > > to
>> > > > > > >> > get
>> > > > > > >> > > parents of that scan set with traits of the PhysicalScan.
>> > > Since
>> > > > > > there
>> > > > > > >> are
>> > > > > > >> > > no such parents (we skipped it intentionally), the rule
>> is
>> > not
>> > > > > > queued.
>> > > > > > >> > >
>> > > > > > >> > > But when converters are enabled, a converter rel is
>> created:
>> > > > > > >> > [LogicalProject]
>> > > > > > >> > > <- [LogicalScan, PhysicalScan,
>> > > ConverterFromPhysicalToLogical].
>> > > > No
>> > > > > > >> rules
>> > > > > > >> > > are fired for PhysicalScan again, but they are fired for
>> > > > converter
>> > > > > > >> since
>> > > > > > >> > > it has the necessary LOGICAL trait.
>> > > > > > >> > >
>> > > > > > >> > > It makes sense, that converters essentially allow forcing
>> > rule
>> > > > > > >> invocation
>> > > > > > >> > > on parents, even if the child was created with different
>> > > traits.
>> > > > > But
>> > > > > > >> it
>> > > > > > >> > > seems that this mechanism may be too heavy for complex
>> > queries
>> > > > > > >> because it
>> > > > > > >> > > literally creates hundreds of new converter rels and
>> > triggers
>> > > > > rules
>> > > > > > >> over
>> > > > > > >> > > and over again.
>> > > > > > >> > >
>> > > > > > >> > > We need some fine-grained alternative. Basically, what
>> would
>> > > be
>> > > > > > enough
>> > > > > > >> > for
>> > > > > > >> > > me is to let the planner know somehow: "I created that
>> rel,
>> > > and
>> > > > I
>> > > > > > want
>> > > > > > >> > you
>> > > > > > >> > > to execute parent rules not only using its trait but
>> also on
>> > > > this
>> > > > > > and
>> > > > > > >> > those
>> > > > > > >> > > traits."
>> > > > > > >> > > Is there any API in Calcite which allows doing this
>> without
>> > > > > > creating a
>> > > > > > >> > new
>> > > > > > >> > > rel node?
>> > > > > > >> > >
>> > > > > > >> > > Regards,
>> > > > > > >> > > Vladimir.
>> > > > > > >> > >
>> > > > > > >> > >
>> > > > > > >> > > ср, 30 окт. 2019 г. в 09:25, Seliverstov Igor <
>> > > > > gvvinbl...@gmail.com
>> > > > > > >:
>> > > > > > >> > >
>> > > > > > >> > >> Vladimir,
>> > > > > > >> > >>
>> > > > > > >> > >> Probably it'll help you:
>> > > > > > >> > >>
>> > > > > > >> > >> Seems the cause of issue in RelSubset.getParentRels()
>> The
>> > > > check
>> > > > > > used
>> > > > > > >> > when
>> > > > > > >> > >> the planner schedules newly matched rules after
>> successful
>> > > > > > >> > transformation
>> > > > > > >> > >> (see VolcanoRuleCall.matchRecurse), it prevents the
>> parent
>> > > rule
>> > > > > be
>> > > > > > >> > applied
>> > > > > > >> > >> once again (here your logical project with an input
>> having
>> > > ANY
>> > > > > > >> > >> distribution
>> > > > > > >> > >> doesn't satisfy a transformed input traits).
>> > > > > > >> > >>
>> > > > > > >> > >> In our case we use another workaround, so there are also
>> > much
>> > > > > more
>> > > > > > >> > >> transformations than we wanted, so the desired rule is
>> > > > triggered.
>> > > > > > >> > >>
>> > > > > > >> > >>
>> > > > > > >> > >> вт, 29 окт. 2019 г., 14:46 Vladimir Ozerov <
>> > > ppoze...@gmail.com
>> > > > >:
>> > > > > > >> > >>
>> > > > > > >> > >> > Hi Vladimir,
>> > > > > > >> > >> >
>> > > > > > >> > >> > I am sorry. Pushed, it works now.
>> > > > > > >> > >> >
>> > > > > > >> > >> > вт, 29 окт. 2019 г. в 14:41, Vladimir Sitnikov <
>> > > > > > >> > >> > sitnikov.vladi...@gmail.com
>> > > > > > >> > >> > >:
>> > > > > > >> > >> >
>> > > > > > >> > >> > > > mvn clean test
>> > > > > > >> > >> > >
>> > > > > > >> > >> > > [ERROR] The goal you specified requires a project to
>> > > > execute
>> > > > > > but
>> > > > > > >> > >> there is
>> > > > > > >> > >> > > no POM in this directory
>> > > > > > >> > >> > >
>> > > > > > >> > >> > > Vladimir, please push missing files
>> > > > > > >> > >> > >
>> > > > > > >> > >> > > Vladimir
>> > > > > > >> > >> > >
>> > > > > > >> > >> >
>> > > > > > >> > >>
>> > > > > > >> > >
>> > > > > > >> >
>> > > > > > >>
>> > > > > > >
>> > > > > >
>> > > > >
>> > > >
>> > >
>> >
>>
>>
>

Reply via email to