Категорія: MySQL

 

Тимчасовий обхід обмеження довжини varchar

В одному з моїх поточних проектів у процесі розробки процесу імпорту великих об’ємів даних виникла задача ефективно (швидко) обійти обмеження довжини varchar полів у базі даних. Фактично, ми готові були пожертвувати частиною даних задля збереження швидкості роботи.

Річ у тім, що MySQL за умовчанням не дозволяє запхати в поле varchar рядок довший за наперед визначену розмірність.

Але це можна обійти скинувши налаштування @@sql_mode.

В якості демонстрації принципу наведу шмат коду, коментарі мають все пояснити.

<!---
CREATE TABLE IF NOT EXISTS contacts (
  contactId int(10) unsigned NOT NULL AUTO_INCREMENT,
  salutation varchar(5) DEFAULT NULL,
  firstname varchar(255) DEFAULT NULL,
  PRIMARY KEY (contactId)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
 --->


<cfset local = {} />
<cfset local.value = "Doctor" />


<!--- save the current SQL mode --->
<cfquery datasource="my_test_dsn" name="local.getSqlMode">
    select @@sql_mode as sqlmode
</cfquery>

<!--- reset the SQL mode --->
<cfquery datasource="my_test_dsn" result="local.resetSqlMode">
    set sql_mode = ''
</cfquery>


<!--- this should work fine --->
<cfquery datasource="my_test_dsn" result="local.pushContact">
    INSERT INTO contacts (salutation, firstname) VALUES ('#local.value#', '#local.value#')
</cfquery>


<!--- restore the SQL mode --->
<cfquery datasource="my_test_dsn" result="local.revertSqlMode">
    set sql_mode = '#local.getSqlMode.sqlmode#'
</cfquery>


<!--- this should fail --->
<cfquery datasource="my_test_dsn" result="local.pushContact">
    INSERT INTO contacts (salutation, firstname) VALUES ('#local.value#', '#local.value#')
</cfquery>


<cfdump var="#local#">

Автор: Сергій Галашин | Опубліковано: 14.09.2010 о 15:51 | Категорії: Gotchas - MySQL -

 

Railo Tips: типи аргументів, відносні шляхи та згенеровані ключі

Працюючи над портуванням проекту під Railo стикаюся з різними особливостями роботи двигуна, котрі варто пам'ятати щоб не наступати на ці граблі надалі.

 

Спершу виникла проблема з nullable атрибутами в Transfer ORM. В моєму випадку NULL для поля з типом DATE зручно було використовувати для дати завершення строку дії рахунку. Для цього дефініція виглядала наступним чином:

<property name="expirationDate" type="date" column="exp_date" nullable="true" />

Тоді методи object.setExpirationDateNull() / object.getExpirationDateIsNull() давали потрібний результат.

Transfer зберігає NULL-дати в своєму особливому форматі (фактично, дата в далекому минулому), але при витягання NULL з бази все одно ColdFusion конвертував його в порожій рядок. Цей факт і став фатальним при передачі витягнутого значення сеттерові setExpirationDate(<date>).

Railo, на відміну від CF8, не бажає сприймати порожній рядок як коректну дату при передачі його аргументом функції.

Внаслідок цього довелося відмовитися від nullable атрибутів та трішки переробити спосіб відслідковування дат завершення строку.

 

UPDATE

Насправді, це виявилося проблемою коду, що взаємодіяв з Transfer. Бо несприйняття порожнього рядку є нормальним явищем для будь-якого CFML парсера.

 

Іншою проблемою стало використання наступного методу ініціалізації об'єкта:

variables.logBean = CreateObject("component", "model/LogBean").init( arguments.pageid, arguments.userid );

Такий відносний шлях не спрацював в Railo.

На щастя, динамічні мапінги в ньому працюють, тому я використав вже існуючий і переробив код наступним чином:

variables.logBean = CreateObject("component", "components.core.model.LogBean").init( arguments.pageid, arguments.userid );

 

Наостанок мене трохи розчарував той факт, що Railo не дістає останній доданий ключ в result запиту, зокрема для MySQL там не встановлюється GENERATED_KEY взагалі (додано 30.11.2009 -- виправлено!). В якості тимчасового рішення використав наступний спосіб:

<cflock name="#this.lockName#" type="exclusive" timeout="5">

    <!--- push bean into the db ---->
    <cfquery datasource="#variables.dsn#" name="qAddLogEvent" result="qResult">
        INSERT INTO #variables.tableLogCurrent#
            (id_page, id_user, log_type, log_message, log_detail, remote_ip, moment)
        VALUES
            (
             <cfqueryparam cfsqltype="cf_sql_integer" value="#logBean.getPageId()#" />,
             <cfqueryparam cfsqltype="cf_sql_integer" value="#logBean.getUserId()#" />,
             <cfqueryparam cfsqltype="cf_sql_char" value="#logBean.getLogType()#" />,
             <cfqueryparam cfsqltype="cf_sql_char" value="#logBean.getLogMessage()#" />,
             <cfqueryparam cfsqltype="cf_sql_char" value="#logBean.getLogDetail()#" />,
             <cfqueryparam cfsqltype="cf_sql_char" value="#logBean.getRemoteIp()#" />,
             <cfqueryparam cfsqltype="cf_sql_timestamp" value="#logBean.getMoment()#" />
            )
    </cfquery>

    <!--- this is a workaround for the engines not supporting GENERATED_KEY --->
    <cfif NOT StructKeyExists(qResult, "GENERATED_KEY")>

         <cfquery datasource="#variables.dsn#" name="qResult">
             SELECT LAST_INSERT_ID() AS GENERATED_KEY
         </cfquery>

    </cfif>

</cflock>

Хорошою ж новиною є те, що цей прикрий факт можна змінити. Для цього треба проголосувати у відповідному запитові Uservoice. Знаючи лояльність розробників я вірю, що потрібні зміни будуть доволі скоро.

 

Автор: Сергій Галашин | Опубліковано: 27.09.2009 о 18:03 | Категорії: MySQL - ORM - Railo - Subjective - Tips - Transfer -

 

Null Pointers Are Another Name For Undefined Values

Недавно в сайтах на Coldfusion 8 стала появлятся такая вот непонятная ошибка

The system has attempted to use an undefined value, which usually indicates a programming error, either in your code or some system code.

Null Pointers are another name for undefined values.

Ошибка "лечилась" простой перезагрузкой вызываемой страницы (F5), казалось что это и не ошибка вовсе. Дебаггер не выводил ничего путного, строки, на которые указывала Coldfusion не содержали ничего близко похожего, и к тому же всегда разнились.

После гугления прояснилось. Все эти сайты были построены на MySQL 5. Дело было в настройке для MySQL датасорса - "Maintain Connections" - по-умолчанию установленной в true. Coldfusion пыталась не закрывать коннекшен, и вероятно, MySQL делала это в одностороннем порядке. При попытке соединится с базой, Coldfusion падала с такой неясной ошибкой.

Чтобы отключить эту опцию, в Coldfusion Administrator -> Datasources при редактировании источника данных нажмите кнопку Show Advanced Settings и снимите галочку "Maintain Connections".

Автор: Родион Быков | Опубліковано: 28.08.2008 о 08:05 | Категорії: MySQL - Settings -