ActiveRecord and GetHashCode fails if int is nullable - subsonic3

There is a problem when the int is nullable on GetHashCode
At the point of GetHashCode on ActiveRecord.tt there is a need for a nullable check.
Something like this.
<#
if(tbl.PK.SysType=="int" && !tbl.PK.Nullable ){
#>
public override int GetHashCode() {
return this.<#=tbl.PK.CleanName #>;
}
<# }#>
(update)
This value can be come null on the Views.
I have include the views using this code I found on inet.
const string TABLE_SQL=#"SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
union
select Table_catalog, table_schema, table_name, 'View' table_type
from information_schema.views";
After that, this error appears.

SubSonic requires a primary key that is not null. You need to modify your view so it returns an Id column that is a non null Integer or Guid.
EDIT: You can add a non null primary key that'll work for SubSonic by changing your view as follows:
CREATE VIEW MyView AS
SELECT NewID() AS Id, *
FROM MyTable
The one drawback is that you won't get a consistent Id. If that's a problem you could replace NewID() with a value computed from the column but the drawback of that is the performance will be slower.

Related

Change type of record column in BigQuery

I have a table in BigQuery with a RECORD type column. This RECORD column is just a RECORD, it's not a REPEATED column. I would like to change the type of one of the elements in the record. My record is defined as:
product_action RECORD NULLABLE
product_action.action_type INTEGER NULLABLE
product_action.checkout_step INTEGER NULLABLE
I would like to change the type of ACTION_TYPE from INTEGER to STRING, but I don't know how to do it. I know it involves selecting and casting to a new table, but I don't know the right syntax. There is a very similar question here with an answer
How to change the col type of a BigQuery repeated record
but it's only for REPEATED records and was not able to change it to RECORD only (not REPEATED).
Thanks!
Potential problem with OP's answer is that it does not preserve original order of fields in record, so it ends up with below schema
product_action RECORD NULLABLE
product_action.checkout_step INTEGER NULLABLE
product_action.action_type STRING NULLABLE <-- Type and position changed
instead of
product_action RECORD NULLABLE
product_action.action_type STRING NULLABLE <-- Type changed while position preserved
product_action.checkout_step INTEGER NULLABLE
Below handles this issue
#standardSQL
SELECT * REPLACE((
SELECT AS STRUCT product_action.* REPLACE(
CAST(product_action.action_type AS STRING) AS action_type
)) AS product_action)
FROM `mytable`
Got it working finally
SELECT
* REPLACE
(
(
SELECT
AS STRUCT product_action.* EXCEPT (action_type),
CAST(product_action.action_type AS STRING) AS action_type
) AS product_action
),
FROM
`mytable`

How to format the id column with SHA1 digests in Rails application?

Without saving SHA1 digest string in table directly. Is it possible to format the column in select statement ?
For example (Hope you know what i mean):
#item = Item.where(Digest::SHA1.hexdigest id.to_s:'356a192b7913b04c54574d18c28d46e6395428ab')
No, not the way you want it. The hexdigest method you're using won't be available at the database level. You could use database-specific functions though.
For example:
Item.where("LOWER(name) = ?", entered_name.downcase)
The LOWER() function will be available to the database so it can pass the name column to it.
For your case, I can suggest two solutions:
Obviously, store the encrypted field in the table. And then match.
key = '356a192b7913b04c54574d18c28d46e6395428ab'
Item.where(encrypted_id: key)
Iterate over all column values (ID, in your case) and find the one that matches:
all_item_ids = Item.pluck("CAST(id AS TEXT)")
item_id = all_item_ids.find{ |val| Digest::SHA1.hexdigest(val) == key }
Then you could use Item.find(item_id) to get the item or Item.where(id: item_id) to get an ActiveRecord::Relation object.

Why do sqlite columns have different names for views and tables?

For this sample database:
create table atable (
textfield varchar(256)
);
create view aview as select T.textfield from atable T;
and these selects:
select T.textfield from atable T;
select T.textfield from aview T;
calling sqlite's sqlite3_column_name(...) yields different results for the select on view and on table. In case of table the the alias is not included, in case of view it is.
Here are the results:
table query - sqlite3_column_name (db, 0) -> "textfield"
view query - sqlite3_column_name (db, 0) -> "T.textfield"
Why are these different?
Surprisingly, SQLITE provides no guarantees to the column name returned by sqlite_3_column_name unless you specifically provide the name using AS keyword.
From sqlite3_column_name function documentation:
The name of a result column is the value of the "AS" clause for that
column, if there is an AS clause. If there is no AS clause then the
name of the column is unspecified and may change from one release of
SQLite to the next.
Therefore you have to manually specify the column names if you want to depend on the value returned. Change your queries to :
select T.textfield as textfield from atable T;
select T.textfield as textfield from aview T;
and in both cases sqlite3_column_name will return textfield.

subquery in join with doctrine dql

I want to use DQL to create a query which looks like this in SQL:
select
e.*
from
e
inner join (
select
uuid, max(locale) as locale
from
e
where
locale = 'nl_NL' or
locale = 'nl'
group by
uuid
) as e_ on e.uuid = e_.uuid and e.locale = e_.locale
I tried to use QueryBuilder to generate the query and subquery. I think they do the right thing by them selves but I can't combine them in the join statement. Does anybody now if this is possible with DQL? I can't use native SQL because I want to return real objects and I don't know for which object this query is run (I only know the base class which have the uuid and locale property).
$subQueryBuilder = $this->_em->createQueryBuilder();
$subQueryBuilder
->addSelect('e.uuid, max(e.locale) as locale')
->from($this->_entityName, 'e')
->where($subQueryBuilder->expr()->in('e.locale', $localeCriteria))
->groupBy('e.uuid');
$queryBuilder = $this->_em->createQueryBuilder();
$queryBuilder
->addSelect('e')
->from($this->_entityName, 'e')
->join('('.$subQueryBuilder.') as', 'e_')
->where('e.uuid = e_.uuid')
->andWhere('e.locale = e_.locale');
You cannot put a subquery in the FROM clause of your DQL.
I will assume that your PK is {uuid, locale}, as of discussion with you on IRC. Since you also have two different columns in your query, this can become ugly.
What you can do is putting it into the WHERE clause:
select
e
from
MyEntity e
WHERE
e.uuid IN (
select
e2.uuid
from
MyEntity e2
where
e2.locale IN (:selectedLocales)
group by
e2.uuid
)
AND e.locale IN (
select
max(e3.locale) as locale
from
MyEntity e3
where
e3.locale IN (:selectedLocales)
group by
e3.uuid
)
Please note that I used a comparison against a (non empty) array of locales that you bind to to the :selectedLocales. This is to avoid destroying the query cache if you want to match against additional locales.
I also wouldn't suggest building this with the query builder if there's no real advantage in doing so since it will just make it simpler to break the query cache if you add conditionals dynamically (also, it's 3 query builders involved!)

query builder select the id from leftJoin

I have a select field that fetch from an entity
and I would like to customize completely my select by choosing the table the id is picked from
(here I would like to select t.id instead of tl.id as the select value)
return $er->createQueryBuilder('tl')
->addSelect('l')
->addSelect('t')
->leftJoin('tl.lang', 'l')
->leftJoin('tl.type', 't')
->where('l.isDefault = 1')
->orderBy('tl.name', 'ASC');
Due to my tables, I can't simply fetch the table t, I have to use tl
Your query is not according to the syntax defined in Doctrine 2 QueryBuilder: http://www.doctrine-project.org/docs/orm/2.0/en/reference/query-builder.html
Your query might work in Doctrine 1.2 but in Doctrine 2 you should build your query according to the syntax defined in the link I posted above.
For example ->addSelect('l') is not being used in Doctrine 2 anymore. It has become ->add('select', 'l').
You don't have to set different alias for your column. It'll be hydrated as column of the related entity.