[JBoss JIRA] (TEIID-4594) Add ability to read Parquet Files
by Steven Hawkins (JIRA)
[ https://issues.jboss.org/browse/TEIID-4594?page=com.atlassian.jira.plugin... ]
Steven Hawkins reassigned TEIID-4594:
-------------------------------------
Fix Version/s: 9.3
Priority: Critical (was: Blocker)
Assignee: (was: Steven Hawkins)
Based upon the product JIRA this may still be needed, just not in 9.2.
> Add ability to read Parquet Files
> ---------------------------------
>
> Key: TEIID-4594
> URL: https://issues.jboss.org/browse/TEIID-4594
> Project: Teiid
> Issue Type: Feature Request
> Components: Misc. Connectors
> Affects Versions: 9.2
> Reporter: Van Halbert
> Priority: Critical
> Fix For: 9.3
>
>
> Integration with Parquet files on Gluster is an important requirement. RADAnalytics will be accessing data from Parquet which is a common file format for Spark.
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4610) Impala regexp_replace function colliding with prepared values
by Steven Hawkins (JIRA)
[ https://issues.jboss.org/browse/TEIID-4610?page=com.atlassian.jira.plugin... ]
Steven Hawkins commented on TEIID-4610:
---------------------------------------
Can you provide the full stacktrace? I don't see how this is related to regexp_replace.
> Impala regexp_replace function colliding with prepared values
> -------------------------------------------------------------
>
> Key: TEIID-4610
> URL: https://issues.jboss.org/browse/TEIID-4610
> Project: Teiid
> Issue Type: Bug
> Components: Misc. Connectors
> Affects Versions: 8.13.3
> Reporter: Scott Wallace
> Assignee: Steven Hawkins
>
> Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
> select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
> from some_impala_table
> where date_key = concat(substring('2016-01-15',1,7),'-01')
> and customer_id = 112
> Error:
> {noformat}
> org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4610) Impala regexp_replace function colliding with prepared values
by Scott Wallace (JIRA)
[ https://issues.jboss.org/browse/TEIID-4610?page=com.atlassian.jira.plugin... ]
Scott Wallace commented on TEIID-4610:
--------------------------------------
Hi Steven - Jira was formatting the actual error in the description. I updated, so that Jira doesn't manipulate the actual error. Does that help?
> Impala regexp_replace function colliding with prepared values
> -------------------------------------------------------------
>
> Key: TEIID-4610
> URL: https://issues.jboss.org/browse/TEIID-4610
> Project: Teiid
> Issue Type: Bug
> Components: Misc. Connectors
> Affects Versions: 8.13.3
> Reporter: Scott Wallace
> Assignee: Steven Hawkins
>
> Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
> select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
> from some_impala_table
> where date_key = concat(substring('2016-01-15',1,7),'-01')
> and customer_id = 112
> Error:
> {noformat}
> org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4610) Impala regexp_replace function colliding with prepared values
by Scott Wallace (JIRA)
[ https://issues.jboss.org/browse/TEIID-4610?page=com.atlassian.jira.plugin... ]
Scott Wallace updated TEIID-4610:
---------------------------------
Description:
Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
from some_impala_table
where date_key = concat(substring('2016-01-15',1,7),'-01')
and customer_id = 112
Error:
{noformat}
org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
{noformat}
was:
Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
from some_impala_table
where date_key = concat(substring('2016-01-15',1,7),'-01')
and customer_id = 112
Error:
org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
> Impala regexp_replace function colliding with prepared values
> -------------------------------------------------------------
>
> Key: TEIID-4610
> URL: https://issues.jboss.org/browse/TEIID-4610
> Project: Teiid
> Issue Type: Bug
> Components: Misc. Connectors
> Affects Versions: 8.13.3
> Reporter: Scott Wallace
> Assignee: Steven Hawkins
>
> Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
> select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
> from some_impala_table
> where date_key = concat(substring('2016-01-15',1,7),'-01')
> and customer_id = 112
> Error:
> {noformat}
> org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
> {noformat}
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4610) Impala regexp_replace function colliding with prepared values
by Scott Wallace (JIRA)
[ https://issues.jboss.org/browse/TEIID-4610?page=com.atlassian.jira.plugin... ]
Scott Wallace updated TEIID-4610:
---------------------------------
Description:
Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
from some_impala_table
where date_key = concat(substring('2016-01-15',1,7),'-01')
and customer_id = 112
Error:
org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
was:
Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
Error:
{{org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01 00:00:00.0'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`date_key` = ? AND g_0.`customer_id` = 112]}}
> Impala regexp_replace function colliding with prepared values
> -------------------------------------------------------------
>
> Key: TEIID-4610
> URL: https://issues.jboss.org/browse/TEIID-4610
> Project: Teiid
> Issue Type: Bug
> Components: Misc. Connectors
> Affects Versions: 8.13.3
> Reporter: Scott Wallace
> Assignee: Steven Hawkins
>
> Impala regexp_replace function appears to collide with prepared values only when attemping to replace apostrophe.
> select impala.regexp_replace(string_column,char(39),concat('&apos',char(59)))
> from some_impala_table
> where date_key = concat(substring('2016-01-15',1,7),'-01')
> and customer_id = 112
> Error:
> org.teiid.runtime.client.TeiidClientException: java.lang.RuntimeException: Remote org.teiid.core.TeiidProcessingException: TEIID30504 warehouse: 500051 TEIID11008:TEIID11004 Error executing statement(s): [Prepared Values: ['2016-01-01'] SQL: SELECT regexp_replace(g_0.`string_column`, '\'', ''') FROM some_impala_table g_0 WHERE g_0.`process_date_key` = ? AND g_0.`customer_id` = 112]
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4613) OData client does not support old servers for boolean functions
by Damien B (JIRA)
Damien B created TEIID-4613:
-------------------------------
Summary: OData client does not support old servers for boolean functions
Key: TEIID-4613
URL: https://issues.jboss.org/browse/TEIID-4613
Project: Teiid
Issue Type: Bug
Components: OData
Affects Versions: 9.1.1
Reporter: Damien B
Assignee: Steven Hawkins
Some old data servers does not support to be called with a filter containing a boolean function and a operator (like "Customers?$filter=substringof('Alfreds', CompanyName) eq true"), they instead want a unary operation (i.e. "Customers?$filter=substringof('Alfreds', CompanyName)"). translator-odata forces the operator presence.
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4595) Wrong pushdown of several spatial functions to Oracle
by Steven Hawkins (JIRA)
[ https://issues.jboss.org/browse/TEIID-4595?page=com.atlassian.jira.plugin... ]
Steven Hawkins commented on TEIID-4595:
---------------------------------------
After consulting with Andrej we'll now use just the sdo_ functions rather than the relate form. Also it appears that crosses is implemented by the overlapbdydisjoint function/mask.
> Wrong pushdown of several spatial functions to Oracle
> -----------------------------------------------------
>
> Key: TEIID-4595
> URL: https://issues.jboss.org/browse/TEIID-4595
> Project: Teiid
> Issue Type: Bug
> Affects Versions: 8.12.x
> Reporter: Andrej Šmigala
> Assignee: Steven Hawkins
> Fix For: 9.2, 9.1.2
>
>
> There are several geospatial functions that are wrongly pushed down to oracle
> # {{ST_DISTANCE}} is pushed as {{SDO_GEOM.DISTANCE}} which does not exist, should be {{SDO_GEOM.SDO_DISTANCE}}. This results in runtime error.
> # {{ST_CROSSES}} and {{ST_OVERLAPS}} are both pushed as {{SDO_RELATE}} with mask {{"overlapbydisjoint"}} which does not exists, should be {{"overlapbdydisjoint"}} (sic} for {{ST_CROSSES}} and {{"overlapbdyintersect"}} for {{ST_OVERLAPS}}. This results in {{false}} being returned for all calls to the two functions
> # Using {{ST_DISJOINT}} in the select clause (but not in criteria) results in the following error when evaluating to true:
> {noformat}
> org.teiid.jdbc.TeiidSQLException: TEIID30504 Remote org.teiid.core.TeiidProcessingException: TEIID30504 SpatialModel: 99999 Unexpected exception while translating results: Fail to convert to internal representation
> at org.teiid.jdbc.TeiidSQLException.create(TeiidSQLException.java:135)
> at org.teiid.jdbc.TeiidSQLException.create(TeiidSQLException.java:71)
> at org.teiid.jdbc.StatementImpl.postReceiveResults(StatementImpl.java:706)
> at org.teiid.jdbc.StatementImpl.access$100(StatementImpl.java:64)
> at org.teiid.jdbc.StatementImpl$2.onCompletion(StatementImpl.java:545)
> at org.teiid.client.util.ResultsFuture.done(ResultsFuture.java:135)
> at org.teiid.client.util.ResultsFuture.access$200(ResultsFuture.java:40)
> at org.teiid.client.util.ResultsFuture$1.receiveResults(ResultsFuture.java:79)
> at org.teiid.net.socket.SocketServerInstanceImpl.receivedMessage(SocketServerInstanceImpl.java:268)
> at org.teiid.net.socket.SocketServerInstanceImpl.read(SocketServerInstanceImpl.java:306)
> at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at org.teiid.net.socket.SocketServerConnectionFactory$ShutdownHandler.invoke(SocketServerConnectionFactory.java:98)
> at com.sun.proxy.$Proxy18.read(Unknown Source)
> at org.teiid.net.socket.SocketServerInstanceImpl$RemoteInvocationHandler$1.get(SocketServerInstanceImpl.java:405)
> at org.teiid.jdbc.StatementImpl.executeSql(StatementImpl.java:554)
> at org.teiid.jdbc.StatementImpl.execute(StatementImpl.java:1060)
> at org.teiid.jdbc.StatementImpl.execute(StatementImpl.java:323)
> at org.jboss.bqt.framework.AbstractQuery.execute(AbstractQuery.java:208)
> at org.jboss.bqt.client.testcase.ProcessResults.executeTest(ProcessResults.java:280)
> at org.jboss.bqt.client.testcase.ProcessResults.runTestCase(ProcessResults.java:166)
> at org.jboss.bqt.client.TestClient.runScenario(TestClient.java:209)
> at org.jboss.bqt.client.TestClient.runTest(TestClient.java:132)
> at org.jboss.bqt.client.TestClient.runTest(TestClient.java:113)
> at org.jboss.qe.bqt.BQTHelper.startTest(BQTHelper.java:59)
> at org.jboss.dv.test.bqt.Utils.runScenarioTest(Utils.java:185)
> at org.jboss.dv.test.bqt.TestPassRDBMS.testRdbms(TestPassRDBMS.java:210)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
> at org.testng.internal.MethodInvocationHelper$1.runTestMethod(MethodInvocationHelper.java:197)
> at org.jboss.qe.DVQETestListener.run(DVQETestListener.java:266)
> at org.testng.internal.MethodInvocationHelper.invokeHookable(MethodInvocationHelper.java:209)
> at org.testng.internal.Invoker.invokeMethod(Invoker.java:639)
> at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:820)
> at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1128)
> at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
> at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
> at org.testng.TestRunner.privateRun(TestRunner.java:782)
> at org.testng.TestRunner.run(TestRunner.java:632)
> at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
> at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
> at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
> at org.testng.SuiteRunner.run(SuiteRunner.java:268)
> at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
> at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
> at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
> at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
> at org.testng.TestNG.run(TestNG.java:1064)
> at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:70)
> at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
> at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
> at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
> at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
> at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:172)
> at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:104)
> at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:70)
> Caused by: org.teiid.core.TeiidProcessingException: TEIID30504 Remote org.teiid.core.TeiidProcessingException: TEIID30504 SpatialModel: 99999 Unexpected exception while translating results: Fail to convert to internal representation
> at org.teiid.dqp.internal.process.DataTierTupleSource.exceptionOccurred(DataTierTupleSource.java:401)
> at org.teiid.dqp.internal.process.DataTierTupleSource.nextTuple(DataTierTupleSource.java:161)
> at org.teiid.query.processor.relational.AccessNode.nextBatchDirect(AccessNode.java:391)
> at org.teiid.query.processor.relational.RelationalNode.nextBatch(RelationalNode.java:282)
> at org.teiid.query.processor.relational.RelationalPlan.nextBatch(RelationalPlan.java:145)
> at org.teiid.query.processor.QueryProcessor.nextBatchDirect(QueryProcessor.java:151)
> at org.teiid.query.processor.QueryProcessor.nextBatch(QueryProcessor.java:114)
> at org.teiid.query.processor.BatchCollector.collectTuples(BatchCollector.java:164)
> at org.teiid.query.processor.BatchCollector.collectTuples(BatchCollector.java:146)
> at org.teiid.dqp.internal.process.RequestWorkItem.processMore(RequestWorkItem.java:472)
> at org.teiid.dqp.internal.process.RequestWorkItem.process(RequestWorkItem.java:348)
> at org.teiid.dqp.internal.process.AbstractWorkItem.run(AbstractWorkItem.java:51)
> at org.teiid.dqp.internal.process.RequestWorkItem.run(RequestWorkItem.java:274)
> at org.teiid.dqp.internal.process.DQPWorkContext.runInContext(DQPWorkContext.java:280)
> at org.teiid.dqp.internal.process.ThreadReuseExecutor$RunnableWrapper.run(ThreadReuseExecutor.java:119)
> at org.teiid.dqp.internal.process.ThreadReuseExecutor$3.run(ThreadReuseExecutor.java:210)
> at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
> at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
> at java.lang.Thread.run(Thread.java:745)
> Caused by: org.teiid.core.TeiidException: 99999 Remote org.teiid.translator.TranslatorException: 99999 Unexpected exception while translating results: Fail to convert to internal representation
> at org.teiid.translator.jdbc.JDBCQueryExecution.next(JDBCQueryExecution.java:351)
> at org.teiid.dqp.internal.datamgr.ConnectorWorkItem.handleBatch(ConnectorWorkItem.java:436)
> at org.teiid.dqp.internal.datamgr.ConnectorWorkItem.more(ConnectorWorkItem.java:236)
> at sun.reflect.GeneratedMethodAccessor88.invoke(Unknown Source)
> at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
> at java.lang.reflect.Method.invoke(Method.java:498)
> at org.teiid.dqp.internal.datamgr.ConnectorManager$1.invoke(ConnectorManager.java:211)
> at com.sun.proxy.$Proxy47.more(Unknown Source)
> at org.teiid.dqp.internal.process.DataTierTupleSource.getResults(DataTierTupleSource.java:309)
> at org.teiid.dqp.internal.process.DataTierTupleSource$1.call(DataTierTupleSource.java:112)
> at org.teiid.dqp.internal.process.DataTierTupleSource$1.call(DataTierTupleSource.java:108)
> at java.util.concurrent.FutureTask.run(FutureTask.java:266)
> at org.teiid.dqp.internal.process.FutureWork.run(FutureWork.java:65)
> ... 6 more
> Caused by: java.sql.SQLException: Remote java.sql.SQLException: Fail to convert to internal representation
> at oracle.jdbc.driver.CharCommonAccessor.getBoolean(CharCommonAccessor.java:183)
> at oracle.jdbc.driver.GeneratedStatement.getBoolean(GeneratedStatement.java:129)
> at oracle.jdbc.driver.GeneratedScrollableResultSet.getBoolean(GeneratedScrollableResultSet.java:232)
> at org.jboss.jca.adapters.jdbc.WrappedResultSet.getBoolean(WrappedResultSet.java:594)
> at org.teiid.translator.jdbc.JDBCExecutionFactory.retrieveValue(JDBCExecutionFactory.java:1068)
> at org.teiid.translator.jdbc.JDBCQueryExecution.next(JDBCQueryExecution.java:344)
> ... 18 more
> {noformat}
> This is because it is pushed down as {{SDO_GEOM.RELATE}} with mask {{"disjoint"}}, which in oracle returns the string {{'DISJOINT'}} instead of the more expected {{'TRUE'}}.
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years
[JBoss JIRA] (TEIID-4597) Issue loading staging table
by Steven Hawkins (JIRA)
[ https://issues.jboss.org/browse/TEIID-4597?page=com.atlassian.jira.plugin... ]
Steven Hawkins resolved TEIID-4597.
-----------------------------------
Fix Version/s: (was: 8.12.8.6_3)
Resolution: Done
Merged the pull request
> Issue loading staging table
> ---------------------------
>
> Key: TEIID-4597
> URL: https://issues.jboss.org/browse/TEIID-4597
> Project: Teiid
> Issue Type: Bug
> Components: Misc. Connectors
> Affects Versions: 8.12.x
> Reporter: Van Halbert
> Assignee: Van Halbert
> Priority: Blocker
> Fix For: 9.2
>
>
> In the metadata processor, the loading of the staging table doesn't get loaded due to the isStaging() method return false.
> This jira is created so that this issue is documented, as the fix is included in the commit for TEIID-4588 because this has to be fixed in order to see the duplicate column issue in TEIID-4588.
--
This message was sent by Atlassian JIRA
(v7.2.3#72005)
8 years