why zend_db_select does not pick up schema from config file? and how can i fix it?
config:
resources.database.adapter = "Oracle"
resources.database.params.dbname = "(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = x.x.x.x)(PORT = 1521)) (CONNECT_DATA = (SID = xx)))"
resources.database.params.username = ''
resources.database.params.password = ''
resources.database.params.trace =
resources.database.params.schema = YYY
select:
$select->from(
array('pm' => 'tab_1'),
array(
'pm_id',
'status',
'pm_status',
'pm_tabno',
'pm_cardno',
'pm_start_dt',
'pm_endtk_dt',
'pm_signature',
'pm_servrec_no',
'pm_isdirector'
)
)
->joinLeft(
array('pa' => 'tab_2'),
'pm.pm_id = pa.pa_pm',
array(
'PRL_NAME',
'PRF_NAME',
'PRS_NAME'
)
)
->joinLeft(
array('ddpst' => 'tab_3'),
'pm.status = ddpst.dic_value',
'dic_name'
)
->joinLeft(
array('pst' => 'tab_4'),
'pm.pm_status = pst.dic_value',
'dic_sname'
)
->where(
'pa.status = 1'
);
result:
SELECT z2.*
FROM (
SELECT z1.*, ROWNUM AS "zend_db_rownum"
FROM (
SELECT pm.pm_id, pm.status, pm.pm_status, pm.pm_tabno, pm.pm_cardno, pm.pm_start_dt, pm.pm_endtk_dt, pm.pm_signature, pm.pm_servrec_no, pm.pm_isdirector, pa.PRL_NAME, pa.PRF_NAME, pa.PRS_NAME, ddpst.dic_name, pst.dic_sname FROM tab_1 pm
LEFT JOIN tab_2 pa ON pm.pm_id = pa.pa_pm
LEFT JOIN tab_3 ddpst ON pm.status = ddpst.dic_value
LEFT JOIN tab_4 pst ON pm.pm_status = pst.dic_value WHERE (pa.status = 1) ORDER BY PRL_NAME ASC
) z1
) z2
WHERE z2."zend_db_rownum" BETWEEN 1 AND 50
Schema doesn't appear to be a valid parameter accepted by Zend_Application_Resrouce_Db or Zend_Db_Adapter_Oracle. You can set the schema from your DbTable classes if you are using Zend_Db_Table_Abstract to define your DbTables.
See Example #4.
rsolved by overriding Zend_Db_Select (_join() for adding default schema) + overriding Zend_Db_Adapter (for returning own Select)
Related
Sorry for my English.
I ran into a mistake with EF Core 5.0.9 when is use Filtered Include and Select in same time and i don't know is a bug or feature. :)
return await _dbContext.User
.Where(u => !u.TOROLT)
.Where(u => ids.Contains(u.Id))
.Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.Select(u => new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = u.EventUsers.First().Id,
IsCelebrated = u.EventUsers.First().IsCelebrated,
IsEventAdmin = u.EventUsers.First().IsEventAdmin,
IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
IsInvited = u.EventUsers.First().IsInvited,
})
.ToListAsync();
In this time the first elements is select is not from filtered include just from a normal include. SQL Script from Profiler:
SELECT
[u].[Id],
[u].[FirstName],
[u].[LastName],
(
SELECT TOP(1) [e].[Id]
FROM [dbo].[EventUser] AS [e]
WHERE [u].[Id] = [e].[UserId]) AS [EventUserId],
(
SELECT TOP(1) [e0].[IsCelebrated]
FROM [dbo].[EventUser] AS [e0]
WHERE [u].[Id] = [e0].[UserId]) AS [IsCelebrated],
(
SELECT TOP(1) [e1].[IsEventAdmin]
FROM [dbo].[EventUser] AS [e1]
WHERE [u].[Id] = [e1].[UserId]) AS [IsEventAdmin],
(
SELECT TOP(1) [e2].[IsInviteAccepted]
FROM [dbo].[EventUser] AS [e2]
WHERE [u].[Id] = [e2].[UserId]) AS [IsInviteAccepted],
(
SELECT TOP(1) [e3].[IsInvited]
FROM [dbo].[EventUser] AS [e3]
WHERE [u].[Id] = [e3].[UserId]) AS [IsInvited]
FROM [dbo].[User] AS [u]
WHERE ([u].[TOROLT] <> CAST(1 AS bit))
AND [u].[Id] IN (2, 1, 3, 4, 5)
But if is separate filtered include and select, than it work's fine, but this select complete record and not the part of him from database:
var a = await _dbContext.User
.Where(u => !u.TOROLT)
.Where(u => ids.Contains(u.Id))
.Include(u => u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId))
.ToListAsync();
return a.Select(u => new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = u.EventUsers.First().Id,
IsCelebrated = u.EventUsers.First().IsCelebrated,
IsEventAdmin = u.EventUsers.First().IsEventAdmin,
IsInviteAccepted = u.EventUsers.First().IsInviteAccepted,
IsInvited = u.EventUsers.First().IsInvited,
})
.ToList();
Any idea why is this, and how can i solve solve this?
THX
Include is completely ignored if you have custom projection Select, so your filter will be also ignored. It is not a bug, Include works only when you get whole entity from query.
Anyway consider to rewrite your query:
var query =
from u in _dbContext.User
where !u.TOROLT && ids.Contains(u.Id)
from eu in u.EventUsers.Where(eu => !eu.TOROLT && eu.EventId == eventId)
.Take(1)
.DefaultIfEmpty()
select new UserDropDownDtoWithInviteData
{
Id = u.Id,
FirstName = u.FirstName,
LastName = u.LastName,
EventUserId = eu.Id,
IsCelebrated = eu.IsCelebrated,
IsEventAdmin = eu.IsEventAdmin,
IsInviteAccepted = eu.IsInviteAccepted,
IsInvited = eu.IsInvited,
};
var result = await query.ToListAsync();
As $GLOBALS['TYPO3_DB'] become obsolete, I am stuck at the following mm query.
$dbObj = $GLOBALS['TYPO3_DB']->exec_SELECT_mm_query('distinct tx_news_domain_model_news.uid',
'sys_category',
'sys_category_record_mm',
'tx_news_domain_model_news',
' AND sys_category_record_mm.uid_local IN ( '.$catUid.' ) AND tx_news_domain_model_news.pid='.$pid.' AND sys_category_record_mm.tablenames="tx_news_domain_model_news"',
'',
'',
''
);
It shows
Call to a member function exec_SELECT_mm_query() on null
Has anyone found any solution?
Thanks
Use the new QueryBuilder and join your relation.
Example (not a tested working example):
$table = 'tx_news_domain_model_news';
$joinTable = 'sys_category_record_mm';
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable($table);
$statement = $queryBuilder
->select('*')
->from($table)
->leftJoin(
$table,
$joinTable,
'categoryMM',
$queryBuilder->expr()->eq(
'categoryMM.uid_foreign',
$queryBuilder->quoteIdentifier('tx_news_domain_model_news.uid')
)
)
->where(
$queryBuilder->expr()->eq('categoryMM.tablenames', $table),
$queryBuilder->expr()->eq('categoryMM.fieldname', 'categories'),
$queryBuilder->expr()->eq(
'categoryMM.uid',
$queryBuilder->createNamedParameter($catUid, \PDO::PARAM_INT)
)
)
->execute();
I'm using this where an older version of news has related contents stored in an MM table.
$selectTable = 'tt_content';
$joinTable = 'tx_news_domain_model_news';
$mmTable = 'tx_news_domain_model_news_ttcontent_mm';
/** #var \TYPO3\CMS\Core\Database\Query\QueryBuilder $queryBuilder */
$queryBuilder = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Database\ConnectionPool::class)->getQueryBuilderForTable('tt_content');
$res = $queryBuilder->select('t.*')->from($selectTable, 't')
->leftJoin('t', $mmTable, 'mm',
$queryBuilder->expr()->andX(
$queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->createNamedParameter($newsRecord['uid'])),
$queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->quoteIdentifier('t.uid'))
)
)
->leftJoin('mm', $joinTable, 'n',
$queryBuilder->expr()->eq('mm.uid_local', $queryBuilder->quoteIdentifier('n.uid'))
)
->where(
$queryBuilder->expr()->gt('n.uid', $queryBuilder->createNamedParameter(0))
)->execute()->fetchAll();
We are implementing a workflow engine with SQLAlchemy.
Two tables in our model are:
class DbAttribute(Base):
__tablename__ = "db_dbattribute"
id = Column(Integer, primary_key = True)
dbnode_id = Column(Integer, ForeignKey('db_dbnode.id'))
key = Column(String(255))
datatype = Column(String(10))
tval = Column(String, default='')
fval = Column(Float, default=None, nullable=True)
ival = Column(Integer, default=None, nullable=True)
bval = Column(Boolean, default=None, nullable=True)
dval = Column(DateTime, default=None, nullable=True)
class DbNode(Base):
__tablename__ = "db_dbnode"
id = Column(Integer, primary_key=True)
uuid = Column(UUID(as_uuid=True), default=uuid_func)
type = Column(String(255), index=True)
label = Column(String(255), index=True, nullable=True)
description = Column(Text(), nullable=True)
ctime = Column(DateTime(timezone=True), default=timezone.now)
mtime = Column(DateTime(timezone=True), default=timezone.now)
Attributes are related to a Node via the dbnode_id foreign key.
I am now working on a query that would return an attribute value (for example tval) and None if this row does not exists because the key is not the right one. This is working on aliased classes now:
select_stmt =select([aliased_attributes.tval]).select_from(
aliased_attributes
).where(and_(
aliased_attributes.key==attrkey,
aliased_attributes.dbnode_id==aliased_node.id
))
exists_stmt = exists(select_stmt)
entity = case([
(
exists_stmt,
select_stmt
),
(
text('true'),
None
)
])
This exits now with the following error:
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) syntax error at or near "SELECT"
I am using SQLAlchemy 1.0.12 and postgresql 9.4.
Any help on what I missed or other ways this could be done better are greatly appreciated
Cheers
Why not just use simple outerjoin?
attrkey = 'my_attr_key'
q = (
session
.query(
DbNode.label,
DbAttribute.tval,
)
.outerjoin(
DbAttribute,
and_(
DbAttribute.dbnode_id == DbNode.id,
DbAttribute.key == attrkey,
)
)
)
I'm getting an error with a query, my question is: can i chain joins?
My first join is to the primary table, but my second join is to the table joined to the primary table. This is the query:
$query = $this->getDbTable()->select()
->from(array('ca' => 'contracts_allotment'),
array('id',
'contracts_rooms_id' => new Zend_Db_Expr("CONCAT(room_type_desc, '-', room_characteristics_desc)")
))
->join(array('cr' => 'contracts_rooms'),
'ca.contract_rooms_id = cr.id',
array())
->join(array('rt' => 'room_types'),
'cr.room_id = rt.id',
array('room_type_desc'))
->join(array('rc' => 'room_characteristics'),
'cr.char_id = rc.id',
array('room_characteristics_desc'))
->where('contract_id = ?', $contractId);
var_dump($this->getDbTable()->fetchAll($query));die;
I'm getting:
Select query cannot join with another table"
The error comes from Zend/Db/Table/Select::assemble()
Here you have some inside assemble():
// Check each column to ensure it only references the primary table
if ($column) {
if (!isset($from[$table]) || $from[$table]['tableName'] != $primary) {
var_dump($from[$table]['tableName'], $primary);die;
require_once 'Zend/Db/Table/Select/Exception.php';
throw new Zend_Db_Table_Select_Exception('Select query cannot join with another table');
}
}
The var_dump() prints:
string(10) "room_types" string(19) "contracts_allotment"
Any idea?
Don't forget to lock the tables when doing joins:
$query = $this->getDbTable()->select()
->setIntegrityCheck(false)
->from(array('ca' => 'contracts_allotment'),
array('id',
'contracts_rooms_id' => new Zend_Db_Expr("CONCAT(room_type_desc, '-', room_characteristics_desc)")
))
->join(array('cr' => 'contracts_rooms'),
'ca.contract_rooms_id = cr.id',
array())
->join(array('rt' => 'room_types'),
'cr.room_id = rt.id',
array('room_type_desc'))
->join(array('rc' => 'room_characteristics'),
'cr.char_id = rc.id',
array('room_characteristics_desc'))
->where('contract_id = ?', $contractId);
->setIntegrityCheck(false) should at least get you a new error.
I cannot rewrite the current DB schema right now BTW, but that's beside the point to the issue I've hit, so please ignore the table structure :D
I'm running this DB query:
my $rs = $dbx->resultset('Result')->search(
{
'result_hnd' => 16078055,
'seasons.outdoor' => 'venue.outdoors',
'seasons.start_date' => { '<=' => 'meet.date_end' },
'seasons.end_date' => { '>=' => 'meet.date_begin' },
},
{
'join' => [
{
'team' => {
'league_teams' => {
'league' => 'seasons',
},
},
},
{
'meet' => 'venue'
},
],
'+select' => ['seasons.season_hnd','seasons.name','seasons.start_date','seasons.end_date','meet.date_begin','meet.date_end'],
'+as' => ['season_hnd','season_name','s_start','s_end','m_start','m_end'],
columns => ['result_hnd'],
group_by => ['seasons.season_hnd'],
}
);
When I run this, I get no results. With DBIC_TRACE on, I see the generated SQL as:
SELECT me.result_hnd, seasons.season_hnd, seasons.name, seasons.start_date, seasons.end_date, meet.date_begin, meet.date_end FROM track.result me JOIN track.team team ON team.team_hnd = me.team_hnd LEFT JOIN track.league_team league_teams ON league_teams.team_hnd = team.team_hnd LEFT JOIN track.league league ON league.league_hnd = league_teams.league_hnd LEFT JOIN track.season seasons ON seasons.league_hnd = league.league_hnd OR seasons.league_hnd = league.parent_league_hnd JOIN track.meet meet ON meet.meet_hnd = me.meet_hnd JOIN track.venue venue ON venue.venue_hnd = meet.venue_hnd WHERE ( ( result_hnd = ? AND seasons.end_date >= ? AND seasons.outdoor = ? AND seasons.start_date <= ? ) ) GROUP BY seasons.season_hnd: '16078055', 'meet.date_begin', 'venue.outdoors', 'meet.date_end'
When I copy and paste this statement into my MYSQL client (and interpolate the placeholders), like this:
SELECT me.result_hnd, seasons.season_hnd, seasons.name, seasons.start_date, seasons.end_date, meet.date_begin, meet.date_end
FROM track.result me
JOIN track.team team ON team.team_hnd = me.team_hnd
LEFT JOIN track.league_team league_teams ON league_teams.team_hnd = team.team_hnd
LEFT JOIN track.league league ON league.league_hnd = league_teams.league_hnd
LEFT JOIN track.season seasons ON seasons.league_hnd = league.league_hnd OR seasons.league_hnd = league.parent_league_hnd
JOIN track.meet meet ON meet.meet_hnd = me.meet_hnd
JOIN track.venue venue ON venue.venue_hnd = meet.venue_hnd
WHERE ( ( result_hnd = 16078055 AND seasons.end_date >= meet.date_begin AND seasons.outdoor = venue.outdoors AND seasons.start_date <= meet.date_end ) )
GROUP BY season_hnd;
I get the exact result I expect (7 records).
This is really bizarre. To all intents and purposes, isn't that exactly the same query? Am I missing something in my debugging? Or is something else happening at the DBIx::Class::ResultSet layer that isn't being dumped?
To tell SQL::Abstract that the value on the right is actually an identifier, you can do the following (as outlined in the docs):
{
'result_hnd' => 16078055,
'seasons.outdoor' => { -ident => 'venue.outdoors' },
'seasons.start_date' => { '<=' => { -ident => 'meet.date_end' } },
'seasons.end_date' => { '>=' => { -ident => 'meet.date_begin' } },
},
To all intents and purposes, isn't that exactly the same query?
(For all intents and purposes, ...)
No. In the log, you have something equivalent to
result_hnd = '16078055'
AND seasons.end_date >= 'meet.date_begin'
AND seasons.outdoor = 'venue.outdoors'
AND seasons.start_date <= 'meet.date_end'
or maybe
result_hnd = 16078055
AND seasons.end_date >= 'meet.date_begin'
AND seasons.outdoor = 'venue.outdoors'
AND seasons.start_date <= 'meet.date_end'
In your attempt, you used
result_hnd = 16078055
AND seasons.end_date >= meet.date_begin
AND seasons.outdoor = venue.outdoors
AND seasons.start_date <= meet.date_end
Sorry, I don't have the solution for you.