DataMapper naming convention clashes with existing MySQL table - ruby

I am working on a MySQL table that is used by another program. What I want to do is to put up a web interface for this database with Sinatra and DataMapper. However, when I declare my property in the DataMapper model, I run into some problem with naming convention.
For example, the field in MySQL table is ControlStationID, and I declared as such, but when DataMapper runs, it change it to control_station_id. Anyway I can rectify this? I can't change the table structure.
Thanks.
Error seen:
DataObjects::SQLError: Unknown column 'control_station_id' in 'field list' (code: 1054, sql state: 42S22, query: SELECT `id`, `control_station_id` FROM `returnmessage` ORDER BY `id`)
MySQL table structure
mysql> show fields from returnmessage;
+-------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------+------+-----+---------+----------------+
| ID | bigint(20) | NO | PRI | NULL | auto_increment |
| ControlStationID | int(11) | YES | | NULL | |
+-------------------+---------------+------+-----+---------+----------------+
My code
class ReturnMessage
include DataMapper::Resource
property :ID, Serial
property :ControlStationID, Integer
end
repository(:default).adapter.resource_naming_convention = lambda do |value|
value.downcase
end

Solution:
property :ControlStationID, Serial, :field=>'ControlStationID'

Related

Elasticsearch for uncertain amount i18n

I am using elasticsearch-php in a laravel project.
I have a products table like below
CREATE TABLE `products` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`title` JSON NOT NULL,
);
The title of each product will have multiple languages, and the type of language is uncertain
+------------+---------------------------------------------------------------------------+
| id | title |
+------------+---------------------------------------------------------------------------+
| 1 |{"en-US":"Toyota Cruiser","ja-JP":"トヨタクルーザー","zh-CN":"丰田酷路泽"} |
+------------+---------------------------------------------------------------------------+
| 2 |{"en-US":"Subaru Outback","ja-JP":"スバルアウトバック"} |
+------------+---------------------------------------------------------------------------+
| 3 |{"zh-CN":"路虎 揽胜","ja-JP":"ランドローバーレンジローバー"} |
+------------+---------------------------------------------------------------------------+
| 4 |{"en-US":"BMW X5"} |
+------------+---------------------------------------------------------------------------+
How can I create a elasticsearch index for products table which supports search in i18n?
Thanks a lot!
I can see you have the language identifier in your database as en-us, zh-cn which means before storing the title, you know the language of product, than you can simply use the multi-field and can add a new language sub-field for all the available languages in Elasticsearch.
You can have a look at all the current supported languages in Elasticsearch and add all the sub-fields in beginning or change the mapping and add a new language sub-field as you get it in your system.

How can I query for the meta data about a PL/SQL record type

If I have a record type like the following:
create or replace PACKAGE ITEM_MANAGEMENT AUTHID CURRENT_USER
as
type item IS RECORD (
id NUMBER,
Description VARCHAR2(30),
Category VARCHAR2(30)
);
END ITEM_MANAGEMENT;
From PL/SQL I can declare a record variable of this type l_item ITEM_MANAGEMENT.Item;
I would like to be able to query the Oracle database for the properties and their types of this record type.
For example if I want to do this for a table I would do the following:
select COLUMN_NAME, DATA_TYPE, DATA_LENGTH
from ALL_TAB_COLUMNS
where 1 = 1
AND OWNER = 'OWNER'
AND TABLE_NAME = 'TABLENAME';
How can I query for the meta data about an PL/SQL record type?
That is a PL/SQL record type you seem to be talking about. Inspecting a PL/SQL record type is only possible if the stored PL/SQL is compiled to collect PLSCOPE identifiers (otherwise, your query will get no data).
I'll post here an example of doing that. But first let me say that I have NEVER had to do this for any production code. What you are trying to do is not "normal", in my experience and perhaps you need to re-evaluate your approach. Anyway, here it is.
-- First, tell your session that all compilations should collect
-- PLSCOPE identifiers. If you neglect to do this, you can always ALTER
-- a package later to recompile it with PLSCOPE identifiers as follows:
-- alter package mypackage compile
-- plscope_settings='IDENTIFIERS:ALL' reuse settings;
ALTER SESSION SET plscope_settings='IDENTIFIERS:ALL';
CREATE OR REPLACE PACKAGE so_test1 AS
TYPE Item IS RECORD (
id NUMBER,
Description VARCHAR2(30),
Category VARCHAR2(30)
);
END so_test1;
-- Now, the information you want will be in DBA_IDENTIFIERS, which is
-- stored hierarchically. This query will print that hierarchy, starting
-- with the definition of your "ITEM" record type.
WITH v AS (
SELECT Line,
Col,
NAME,
TYPE,
USAGE,
USAGE_ID,
USAGE_CONTEXT_ID
FROM USER_IDENTIFIERS
WHERE Object_Name = 'SO_TEST1'
AND Object_Type = 'PACKAGE'
)
SELECT LPAD(' ', 2*(Level-1)) || NAME,
TYPE, USAGE, USAGE_CONTEXT_ID
FROM v
START WITH name = 'ITEM' and type = 'RECORD' and usage = 'DECLARATION'
CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
ORDER SIBLINGS BY Line, Col
/
Sample output:
+---------------+--------------------+-------------+------------------+
| NAME | TYPE | USAGE | USAGE_CONTEXT_ID |
+---------------+--------------------+-------------+------------------+
| ITEM | RECORD | DECLARATION | 1 |
| ID | VARIABLE | DECLARATION | 2 |
| NUMBER | NUMBER DATATYPE | REFERENCE | 3 |
| DESCRIPTION | VARIABLE | DECLARATION | 2 |
| VARCHAR2 | CHARACTER DATATYPE | REFERENCE | 5 |
| CATEGORY | VARIABLE | DECLARATION | 2 |
| VARCHAR2 | CHARACTER DATATYPE | REFERENCE | 7 |
+---------------+--------------------+-------------+------------------+

Force use of primary key in Oracle during search

I have scenario where i need to search & display records from huge tables with lots of rows. I have pre-defined search criteria for my tables for which user can provide the filter & click search .
Considering a sample table :
CREATE TABLE suppliers
( supplier_name varchar2(50) NOT NULL,
address varchar2(50),
city varchar2(50) NOT NULL,
state varchar2(25),
zip_code varchar2(10),
CONSTRAINT "suppliers_pk" PRIMARY KEY (supplier_name, city)
);
INSERT INTO suppliers VALUES ('ABCD','XXXX','YYYY','ZZZZ','95012');
INSERT INTO suppliers VALUES ('EFGH','MMMM','NNNN','OOOO','95010');
INSERT INTO suppliers VALUES ('IJKL','EEEE','FFFF','GGGG','95009');
I have provided the user with search fields as the primary key - supplier_name, city
If he enters both the fields, my query performance will be good since it goes for index scan
SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = 'ZZZZ';
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 102 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| SUPPLIERS | 1 | 102 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | suppliers_pk | 1 | | 1 (0)| 00:00:01 |
However, if he enters only one of the search field, my query performance will go bad since it goes for full table scan
SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' ;
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 102 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| SUPPLIERS | 1 | 102 | 3 (0)| 00:00:01 |
Is there a way to force oracle to think it is a primary key search when i don't have all of the key fields in search , something like below ( which obviously is not working )
SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = city;
Thanks.
You are thinking about this in the wrong way.
The query optimiser will choose what it thinks best execution plan for the query based on the information available at the time the query is parsed (or sometimes when the parameters changed). Generally - if you give it the right information in terms of stats etc, it usually will do a good job.
You might think that you know better than it, but remember that you won't be monitoring this for the life of the database. The data changes, you want the database to be able to react and change the execution plan when it needs to.
That said, if you are set on forcing it to use the index, you can use a hint:
SELECT /*+ INDEX(suppliers suppliers_pk) */
supplier_name, address, city, state, zip_code FROM suppliers where
supplier_name = 'ABCD' ;
A full table scan is not necessarily bad. You have only a few rows in your table, so the optimizer thinks it is better to do a FTS than an index range scan. It will start using the PK index a soon as the RDBMS thinks it is better, i.e. you have lots a rows and the restriction on a certain supplier reduces the result significantly. If you want to search on city only instead of supplier you need another index with city only (or at least starting with city). Keep in mind that you might have to update the table statistics after you have loaded your table with bulk data. It is always important to test query performance with somehow realistic amounts of data.
Index is organised first on supplier_name second on city so it is not possible to use that index for query based on city only.
Please create second index based only on city. This will help your query.

How to copy data to another table without overwrite existing columns

I have 2 tables in my Amazon DynamoDB: Elements and Containers. Hierarchy is that one container can hold few elements.
So Elements look like: uuid, timestamp, container_id, data.
I want to aggregate data from all elements to corresponding container, example:
Elements:
| uuid | container_id | data |
| 1 | 1 | 100 |
| 2 | 1 | 150 |
| 3 | 2 | 100 |
So I want to get in Containers table:
| uuid | data |
| 1 | 250 |
| 2 | 100 |
So, using hive, I wrote script (that starts on EMR cluster):
CREATE EXTERNAL TABLE element (`uuid` string, `container_id ` bigint, `data` double) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES("dynamodb.table.name"="Elements", "dynamodb.column.mapping"="uuid:UUID,container_id:container_id,data:data");
CREATE EXTERNAL TABLE container (`uuid` string, `data` double) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES("dynamodb.table.name"="Containers", "dynamodb.column.mapping"="uuid:UUID,data:data");
INSERT INTO TABLE container SELECT container_id as `uuid` sum(`data`) as `data` FROM element WHERE container_id IS NOT NULL GROUP BY container_id;
And it works good, but now I need to write some additional data to Containers table, so it should be like uuid, data, another_data. But when I perform script above it overwrite all another_data (that are not listed in external table). I try a lot of variants, but can't find solution.
Ok, I've found an answer:
CREATE EXTERNAL TABLE element (`uuid` string, `container_id ` bigint, `data` double) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES("dynamodb.table.name"="Elements", "dynamodb.column.mapping"="uuid:UUID,container_id:container_id,data:data");
CREATE EXTERNAL TABLE container (`uuid` string, `data` double, `another_data` double) STORED BY 'org.apache.hadoop.hive.dynamodb.DynamoDBStorageHandler' TBLPROPERTIES("dynamodb.table.name"="Containers", "dynamodb.column.mapping"="uuid:UUID,data:data,another_data:another_data");
INSERT INTO TABLE container SELECT element.`container_id` as `uuid` sum(element.`data`) as `data`, collect_set(container.`another_data`)[0] as `another_data` FROM element LEFT JOIN container ON (element.`container_id` = container.`uuid`) WHERE element.container_id IS NOT NULL GROUP BY element.container_id;

How should i design my tables for concurrent table scan access?

I need to hold multiple pairs of 70,000 rows and perform a comparison difference like operation between them using a minus operator. At any time there could be comparisons (table scans).
I currently have one table with this sort of design:
primary key (sequenced)
foreign key to identify set
key to identify set #1 or set #2
then the data here i need to minus against
The data would look something like this
| PK | FK | Key | Data |
| 1 | 1 | Left | Some data |
| 1 | 1 | Left | Diff data |
| 1 | 1 | Right | Some data |
My query would be:
SELECT data
FROM diffTable
WHERE pk = 1
AND fk = 1
AND key = 'Left'
MINUS
SELECT data
FROM diffTable
WHERE pk = 1
AND fk = 1
AND key = 'Right'
I am fearing the full table scans will monopolise resources and subsequent inserts and minus' will suffer.
How should I design my tables and why?
create index PK_FK on diff_table
(PK, FK, Key);
The query you posted in your question would run very fast with this index.
Btw, the PK column is not, by itself, the primary key. See the other comments. Perhaps you want:
alter table diff_table
add constraint PK_FK primary key (PK, FK, Key);
maybe pick a better name...

Resources