JavaScript UDF ์ œํ•œ ์‚ฌํ•ญยถ

Snowflake ํ™˜๊ฒฝ ๋‚ด์—์„œ ์•ˆ์ •์„ฑ์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด Snowflake๋Š” JavaScript UDF์— ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ œํ•œ ์‚ฌํ•ญ์„ ์ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ œํ•œ ์‚ฌํ•ญ์€ UDF ์ƒ์„ฑ ์‹œ ํ˜ธ์ถœ๋˜์ง€ ์•Š๊ณ , ์˜คํžˆ๋ ค UDF๊ฐ€ ํ˜ธ์ถœ๋  ๋•Œ ๋Ÿฐํƒ€์ž„์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด ํ•ญ๋ชฉ์—์„œ๋Š” ์ผ๋ฐ˜ JavaScript UDF(์‚ฌ์šฉ์ž ์ •์˜ ํ•จ์ˆ˜) ์š”๊ตฌ ์‚ฌํ•ญ ๋ฐ ์‚ฌ์šฉ ์„ธ๋ถ€ ์ •๋ณด, ๊ทธ๋ฆฌ๊ณ  JavaScript UDF์™€ ๊ด€๋ จ๋œ ์ œํ•œ ์‚ฌํ•ญ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

์ด ํ•ญ๋ชฉ์˜ ๋‚ด์šฉ:

JavaScript ์›๋ณธ ์ฝ”๋“œ์˜ ์ตœ๋Œ€ ํฌ๊ธฐยถ

Snowflake์—์„œ๋Š” JavaScript UDF์˜ ๋ณธ๋ฌธ์—์„œ JavaScript ์†Œ์Šค ์ฝ”๋“œ์˜ ์ตœ๋Œ€ ํฌ๊ธฐ๋ฅผ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค. Snowflake์—์„œ๋Š” ์ด ํฌ๊ธฐ๋ฅผ 100KB๋กœ ์ œํ•œํ•  ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. (์ฝ”๋“œ๋Š” ์••์ถ•๋œ ํ˜•ํƒœ๋กœ ์ €์žฅ๋˜๋ฉฐ ์ •ํ™•ํ•œ ์ œํ•œ์€ ์ฝ”๋“œ์˜ ์••์ถ•๋ฅ ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.)

๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ์‚ฌ์šฉํ•˜๋ฉด UDF๊ฐ€ ์‹คํŒจํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.ยถ

JavaScript UDF๋Š” ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋„ˆ๋ฌด ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์‹คํŒจํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํŠน์ • ์ œํ•œ์€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ๋งŽ์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์™„๋ฃŒํ•˜๋Š” ๋ฐ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋ฉด UDF๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.ยถ

์™„๋ฃŒํ•˜๋Š” ๋ฐ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” JavaScript UDF๋Š” ์ข…๋ฃŒ๋˜์–ด ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ฌดํ•œ ๋ฃจํ”„์— ๋“ค์–ด๊ฐ€๋Š” JavaScript UDF๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

๊ณผ๋„ํ•œ ์Šคํƒ ๊นŠ์ด๋กœ ์ธํ•ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•จยถ

์žฌ๊ท€๋กœ ์ธํ•œ ๊ณผ๋„ํ•œ ์Šคํƒ ๊นŠ์ด๋Š” ์˜ค๋ฅ˜๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

์ „์—ญ ์ƒํƒœยถ

์ผ๋ฐ˜์ ์œผ๋กœ Snowflake๋Š” UDF ๋ฐ˜๋ณต ์‚ฌ์ด์— JavaScript ์ „์—ญ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์‚ฌ์ด์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ „์—ญ ์ƒํƒœ์— ๋Œ€ํ•œ ์ด์ „ ์ˆ˜์ • ์‚ฌํ•ญ์— ์˜์กดํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ชจ๋“  ํ–‰์ด ๋™์ผ JavaScript ํ™˜๊ฒฝ ๋‚ด์—์„œ ์‹คํ–‰๋  ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

์‹ค์ œ๋กœ ์ „์—ญ ์ƒํƒœ๋Š” ๋‹ค์Œ๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋ณต์žกํ•˜๊ฑฐ๋‚˜ ๋ถ€๋‹ด์ด ํฐ ์ดˆ๊ธฐํ™” ๋…ผ๋ฆฌ. ๊ธฐ๋ณธ์ ์œผ๋กœ, ์ œ๊ณต๋œ UDF ์ฝ”๋“œ๋Š” ์ฒ˜๋ฆฌ๋œ ๋ชจ๋“  ํ–‰์— ๋Œ€ํ•ด ํ‰๊ฐ€๋ฉ๋‹ˆ๋‹ค. ํ•ด๋‹น ์ฝ”๋“œ์— ๋ณต์žกํ•œ ๋…ผ๋ฆฌ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์œผ๋ฉด ์ด๋Š” ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • idempotent๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ๊ฐ€ ํฌํ•จ๋œ ํ•จ์ˆ˜. ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    Date.prototype._originalToString = Date.prototype.toString;
    Date.prototype.toString = function() {
      /* ... SOME CUSTOM CODE ... */
      this._originalToString()
      }
    
    Copy

    ์ด ์ฝ”๋“œ๋Š” ์ฒ˜์Œ ์‹คํ–‰๋  ๋•Œ toString ๋ฐ _originalToString ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์€ ์ „์—ญ ์ƒํƒœ๋กœ ์œ ์ง€๋˜๋ฉฐ ์ด ์ฝ”๋“œ๊ฐ€ ๋‘ ๋ฒˆ์งธ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ, ์žฌ๊ท€๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ฐ’์ด ๋‹ค์‹œ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค. toString ์ด ๋‘ ๋ฒˆ์งธ๋กœ ํ˜ธ์ถœ๋˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ฌดํ•œํžˆ ๋ฐ˜๋ณต๋ฉ๋‹ˆ๋‹ค(์Šคํƒ ๊ณต๊ฐ„์ด ์†Œ์ง„๋  ๋•Œ๊นŒ์ง€).

์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ ๊ถŒ์žฅ๋˜๋Š” ํŒจํ„ด์€ JavaScript์˜ ์ „์—ญ ๋ณ€์ˆ˜ ์˜๋ฏธ ์ฒด๊ณ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ด€๋ จ ์ฝ”๋“œ๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ํ‰๊ฐ€๋˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

var setup = function() {
/* SETUP LOGIC */
};

if (typeof(setup_done) === "undefined") {
  setup();
  setup_done = true;  // setting global variable to true
}
Copy

์ด ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ ์ฝ”๋“œ ํ‰๊ฐ€์˜ ํšจ๊ณผ๋ฅผ ์บ์‹œํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™” ํ›„์— ์ „์—ญ ์ปจํ…์ŠคํŠธ๊ฐ€ ๋ชจ๋“  ํ–‰์— ๋Œ€ํ•ด ๋ณด์กด๋œ๋‹ค๋Š” ๋ณด์žฅ์€ ์—†์œผ๋ฉฐ ๋น„์ฆˆ๋‹ˆ์Šค ๋…ผ๋ฆฌ๋Š” ์ด์— ์˜์กดํ•˜์ง€ ์•Š์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌยถ

JavaScript UDF๋Š” ํ‘œ์ค€ JavaScript ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋Œ€ํ•œ ์•ก์„ธ์Šค๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ธŒ๋ผ์šฐ์ €์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๋งŽ์€ ์˜ค๋ธŒ์ ํŠธ์™€ ๋ฉ”์„œ๋“œ๊ฐ€ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. ์ถ”๊ฐ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ํฌํ•จํ•˜๊ฑฐ๋‚˜ ํ˜ธ์ถœํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜์ด ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํ•„์ˆ˜ ์ฝ”๋“œ๋Š” UDF์— ํฌํ•จ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋˜ํ•œ, ๊ธฐ๋ณธ ์ œ๊ณต JavaScript eval() ํ•จ์ˆ˜๊ฐ€ ๋น„ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜๋œ ๋ฒ ๋ฆฌ์–ธํŠธ ํฌ๊ธฐ ๋ฐ ๊นŠ์ดยถ

๋ฐ˜ํ™˜๋œ ๋ฒ ๋ฆฌ์–ธํŠธ ์˜ค๋ธŒ์ ํŠธ์—๋Š” ํฌ๊ธฐ ๋ฐ ์ค‘์ฒฉ ๊นŠ์ด ์ œํ•œ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.

ํฌ๊ธฐ:

ํ˜„์žฌ ๋ช‡ ๋ฉ”๊ฐ€๋ฐ”์ดํŠธ๋กœ ์ œํ•œ๋˜์–ด ์žˆ์ง€๋งŒ, ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊นŠ์ด:

ํ˜„์žฌ ์ค‘์ฒฉ ๊นŠ์ด๋Š” 1000์œผ๋กœ ์ œํ•œ๋˜์ง€๋งŒ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋„ˆ๋ฌด ํฌ๊ฑฐ๋‚˜ ๋„ˆ๋ฌด ๊นŠ์œผ๋ฉด UDF ํ˜ธ์ถœ ์‹œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

์ธ์ž ๋ฐ ๋ฐ˜ํ™˜ ์œ ํ˜• ์ œ์•ฝ ์กฐ๊ฑด์ด ๋•Œ๋•Œ๋กœ ๋ฌด์‹œ๋จยถ

์ธ์ž ๋˜๋Š” ๋ฐ˜ํ™˜ ๊ฐ’์— ๋Œ€ํ•ด ์„ ์–ธ๋œ ํŠน์ • ์œ ํ˜•์˜ ํŠน์„ฑ์€ UDF ํ˜ธ์ถœ ์‹œ ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ ์ˆ˜์‹ ๋œ ๊ฐ’์€ ์„ ์–ธ์— ์ง€์ •๋œ ์ œ์•ฝ ์กฐ๊ฑด์„ ์ค€์ˆ˜ํ•˜๋Š”์ง€ ์—ฌ๋ถ€์— ๊ด€๊ณ„์—†์ด ์ˆ˜์‹ ๋œ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ๋…ผ๋ฆฌ๊ฐ€ JavaScript๋กœ ์ž‘์„ฑ๋œ UDF์— ๋Œ€ํ•ด ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค.

  • VARCHAR ์œ ํ˜•์˜ ์ธ์ž ๊ธธ์ด

์˜ˆยถ

๋‹ค์Œ ์˜ˆ์ œ์˜ ์ฝ”๋“œ๋Š” arg1 ์ธ์ž์™€ ๋ฐ˜ํ™˜ ๊ฐ’์ด 1์ž ์ดํ•˜์˜ VARCHAR์ด์–ด์•ผ ํ•œ๋‹ค๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ฐ’์ด 1์ž๋ณด๋‹ค ๊ธด arg1 ๋กœ ์ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์ œ์•ฝ ์กฐ๊ฑด์ด ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒƒ์ฒ˜๋Ÿผ ์„ฑ๊ณตํ•ฉ๋‹ˆ๋‹ค.

CREATE OR REPLACE FUNCTION tf (arg1 VARCHAR(1))
RETURNS VARCHAR(1)
LANGUAGE JAVASCRIPT AS 'return A.substr(3, 3);';
Copy