How to access tables in other schema in korma? - clojure

In SQL, accessing tables in other schema is simple:
select *
from other_schema.t
where ...
How can I do this in korma? What I actually to do is to access information_schema.tables table. So defining another db by defdb wouldn't be helpful.
I've tried to define the entity, however, failed.
(defentity information_schema.tables)

I've got to know that there is a way to specify the base table when defining an entity. When specifying the base table, it allows to set the schema with ..
(defentity tables
(table :information_schema.tables))
This works fine for accessing information_schema.tables table, without defining another db.

You should be able to do this by defining another db. I can create a db like this:
CREATE database my_db;
USE my_db;
CREATE TABLE stuff (
things VARCHAR(255)
);
INSERT INTO stuff (things) VALUES ("some things");
Now I define two Korma databases and entities, and query them:
(defdb my-db (mysql {:host "localhost"
:port 3306
:db "my_db"
:user "root"
:password nil}))
(defdb information-schema (mysql {:host "localhost"
:port 3306
:db "information_schema"
:user "root"
:password nil}))
(defentity stuff)
(defentity information-schema)
(select stuff
(database my-db))
;; => ({:things "some things"})
(select TABLES
(database information-schema)
(fields :TABLE_SCHEMA :TABLE_NAME)
(where {:TABLE_SCHEMA "my_db"}))
;; => ({:TABLE_NAME "stuff", :TABLE_SCHEMA "my_db"})

Related

AWS error: Invalid operation: table name "?" specified more than once;

the below code works very well in SQL Server 2012, But when I use it in AWS amazon web service will give me a error "Amazon Invalid operation: table name "#t" specified more than once;"
CREATE TABLE #t (store_id varchar(20),city varchar(20),[state] varchar(20));
INSERT INTO #t VALUES
('22', 'new', 'NY'),
('22', null, null),
('22', null, null),
('33', null, null),
('33', 'LA', 'CA')
;
SELECT DISTINCT store_id, city, [state]
INTO #unique
FROM #t WHERE city IS NOT NULL;
;
UPDATE #t
SET city = #unique.city, [state] = #unique.[state]
FROM #unique
INNER JOIN #t
ON #unique.store_id = #t.store_id
WHERE #t.city IS NULL
Does anyone know why and modify my code? Thank you.
Here you go
UPDATE #t
SET city = #unique.city, [state] = #unique.[state]
FROM #unique
WHERE #unique.store_id = #t.store_id
AND #t.city IS NULL
Redshift does not need target table in FROM clause but in case if you need to specify it you need to alias it.
UPDATE #t
SET city = #unique.city, [state] = #unique.[state]
FROM #unique
JOIN #t t1
ON #unique.store_id = t1.store_id
WHERE t1.city IS NULL
From documentation
If you need to include the target table of the UPDATE statement in the list, use an alias.
https://docs.aws.amazon.com/redshift/latest/dg/r_UPDATE.html

Hele converting MSSQL query to Korma entities

I have the below MSSQL query for which I am not able to figure out the Korma entities. Please help out
select t.d as did from (
select dataid as d , count(dataid) as
cd from <table_name>
WHERE prid = <pid> group by dataid
) as t WHERE t.cd >1;
Thanks
SQL Korma documentation site contains subselect sample:
;; Subselects can be used as entities too!
(defentity subselect-example
(table (subselect users
(where {:active true}))
:activeUsers))

has-many does not work

I've got 2 tables
CREATE TABLE public.user_account
(
id integer NOT NULL DEFAULT nextval('user_account_id_seq'::regclass),
email character(50) NOT NULL,
password character(100) NOT NULL,
CONSTRAINT user_account_pkey PRIMARY KEY (id)
)
CREATE TABLE public.recipe
(
id integer NOT NULL DEFAULT nextval('recipe_id_seq'::regclass),
user_account_id integer NOT NULL,
name text NOT NULL,
description text NOT NULL,
CONSTRAINT recipe_pkey PRIMARY KEY (id),
CONSTRAINT recipe_user_account_id_fkey FOREIGN KEY (user_account_id)
REFERENCES public.user_account (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)
This is my clojure declaration
(declare user_account recipe)
(kc/defentity user_account
(kc/entity-fields :email :password)
(kc/has-many recipe {:fk :user_account_id})
)
(kc/defentity recipe
(kc/entity-fields :user_account_id :name :description)
(kc/belongs-to user_account {:fk :user_account_id})
)
And I can not select the user_account table with recipe
user=> (sql-only (kc/select user_account (with recipe) (where {:id 1})))
"SELECT \"user_account\".\"email\", \"user_account\".\"password\" FROM \"user_account\" WHERE (\"user_account\".\"id\" = ?)"
I ran into the same problem. The solution was to addition the pk field to entity-fields list in the parent entity. It really is not intuitive, and seems that the problem is in a poor documentation. So the solution should be:
(declare user_account recipe)
(kc/defentity user_account
(kc/entity-fields :id :email :password)
; ^^^ fix is here
(kc/has-many recipe {:fk :user_account_id})
)
(kc/defentity recipe
(kc/entity-fields :user_account_id :name :description)
(kc/belongs-to user_account {:fk :user_account_id})
)

Unable to SELECT COUNT(*) for Korma entity with default fields

I am unable to SELECT COUNT(*) from an entity I have mapped in Korma.
Here is my entity:
(declare users responses)
(korma/defentity users
(korma/entity-fields :id :slack_id :active :token :token_created)
(korma/many-to-many responses :userresponses))
And here is my attempt at a SELECT COUNT(*):
(korma/select
schema/users
(korma/fields ["count(*)"])
(korma/where {:slack_id slack-id}))
I get this error:
ERROR: column "users.id" must appear in the GROUP BY clause or be used in an aggregate function at character 8
STATEMENT: SELECT "users"."id", "users"."slack_id", "users"."active", "users"."token", "users"."token_created", count(*) FROM "users" WHERE ("users"."slack_id" = $1)
It looks like Korma is including my entity fields even though I'm specifying fields to select in this query. How do I override that?
You can't override it per se. Korma query manipulation functions are always additive, so specifying fields merely specifies additional fields.
To get around this, you can rewrite this query to select against the users table itself rather than the Korma entity users:
(korma/select :users
(korma/fields ["count(*)"])
(korma/where {:slack_id slack-id}))
But then you'll have to make do without anything else defined in the users entity.
Alternatively, you could rewrite this entity to not define any entity-fields, then define a wrapped version of this entity with the desired default fields:
(korma/defentity users-raw
(korma/many-to-many responses :userresponses)))
(def users
(korma/select
users-raw
(korma/fields [:id :slack_id :active :token :token_created])))```
Then you can write your normal queries by adding with/where clauses to this "users" query, and only directly touch users-raw when you need to exclude those fields:
(-> users (with ...) (where ...) (select))

Doctrine2 - use fulltext and MyIsam

I am building an app in Symfony2, using Doctrine2 with mysql. I would like to use a fulltext search. I can't find much on how to implement this - right now I'm stuck on how to set the table engine to myisam.
It seems that it's not possible to set the table type using annotations. Also, if I did it manually by running an "ALTER TABLE" query, I'm not sure if Doctrine2 will continue to work properly - does it depend on the InnoDB foreign keys?
Is there a better place to ask these questions?
INTRODUCTION
Doctrine2 uses InnoDB which supports Foreign Keys used in Doctrine associations. But as MyISAM does not support this yet, you can not use MyISAM to manage Doctrine Entities.
On the other side, MySQL v5.6, currently in development, will bring the support of InnoDB FTS and so will enable the Full-Text search in InnoDB tables.
SOLUTIONS
So there are two solutions :
Using the MySQL v5.6 at your own risks and hacking a bit Doctrine to implement a MATCH AGAINST method : link in french... (I could translate if needed but there still are bugs and I would not recommend this solution)
As described by quickshifti, creating a MyISAM table with fulltext index just to perform the search on. As Doctrine2 allows native SQL requests and as you can map this request to an entity (details here).
EXAMPLE FOR THE 2nd SOLUTION
Consider the following tables :
table 'user' : InnoDB [id, name, email]
table 'search_user : MyISAM [user_id, name -> FULLTEXT]
Then you just have to write a search request with a JOIN and mapping (in a repository) :
<?php
public function searchUser($string) {
// 1. Mapping
$rsm = new ResultSetMapping();
$rsm->addEntityResult('Acme\DefaultBundle\Entity\User', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'name', 'name');
$rsm->addFieldResult('u', 'email', 'email');
// 2. Native SQL
$sql = 'SELECT u.id, u.name FROM search_user AS s JOIN user AS u ON s.user_id = u.id WHERE MATCH(s.name) AGAINST($string IN BOOLEAN MODE)> 0;
// 3. Run the query
$query = $this->_em->createNativeQuery($sql, $rsm);
// 4. Get the results as Entities !
$results = $query->getResult();
return $results;
}
?>
But the FULLTEXT index needs to stay up-to-date. Instead of using a cron task, you can add triggers (INSERT, UPDATE and DELETE) like this :
CREATE TRIGGER trigger_insert_search_user
AFTER INSERT ON user
FOR EACH ROW
INSERT INTO search_user SET user_id=NEW.id, name=NEW.name;
CREATE TRIGGER trigger_update_search_user
AFTER UPDATE ON user
FOR EACH ROW
UPDATE search_user SET name=name WHERE user_id=OLD.id;
CREATE TRIGGER trigger_delete_search_user
AFTER DELETE ON user
FOR EACH ROW
DELETE FROM search_user WHERE user_id=OLD.id;
So that your search_user table will always get the last changes.
Of course, this is just an example, I wanted to keep it simple, and I know this query could be done with a LIKE.
Doctrine ditched the fulltext Searchable feature from v1 on the move to Doctrine2. You will likely have to roll your own support for a fulltext search in Doctrine2.
I'm considering using migrations to generate the tables themselves, running the search queries w/ the native SQL query option to get sets of ids that refer to tables managed by Doctrine, then using said sets of ids to hydrate records normally through Doctrine.
Will probly cron something periodic to update the fulltext tables.