oracle v.11.2. Get md5 hash

select 
  lower(dbms_obfuscation_toolkit.md5(input => utl_raw.cast_to_raw('qwerty'))) md5hash
from dual;

d8578edf8458ce06fbc5bb76a58c5ca4

C. Support private objects in functions

Можно ли добиться поддержки приватности в структурном программировании на C? Javascript может поддерживать приватность за счет техники замыкания, C, конечно, такой возможности не имеет, но можно воспользоваться статическими объектами (с точки зрения класса памяти). Ниже приведен один из подходов

#include <stdio.h>

// init counter action
void init(int *cnt) {
  *cnt = 0;
}

// increment counter action
void increment(int *cnt) {
  (*cnt)++; 
}

// decrement counter action
void decrement(int *cnt) {
  (*cnt)--;
}

// show counter action
void show(const int *cnt) {
  printf("counter = %d\n", *cnt);
}

// counter encapsulation
void counter(void (*action) (int*)) {
  static int cnt = 0; // private
  action(&cnt);
}

int main() {
  
  counter(init);            // counter = 0;
  counter(show);         // counter = 0;
  counter(increment); // counter = 1;
  counter(increment); // counter = 2;
  counter(show);         // counter = 2;

  return 0;
}

В данном случае функции определяют возможные действия над приватным счетчиком, другие действия, как и прямое обращение к значению счетчика (статическая переменная cnt), недопустимы. Можно усложнить данную реализацию для повышения функционала действий над приватным счетчиком. Вот одна из реализаций

#include <stdio.h>
#include <string.h>
#include <stdarg.h>

// check requested init action
int is_init(const char *action) {
  return !strcmp(action, "init");
}

// check requested increment action 
int is_increment(const char *action) {
  return !strcmp(action, "increment");
}

// check requested decrement action
int is_decrement(const char *action) {
  return !strcmp(action, "decrement");


// check requested show action 
int is_show(const char *action) {
  return !strcmp(action, "show");
}

// init counter action
void init(int *cnt) {
  *cnt = 0;
}

// increment counter action
void increment(int *cnt, int n) {
  (*cnt) += n;
}

// decrement counter action
void decrement(int *cnt, int n) {
  (*cnt) -= n;
}

// show counter action
void show(const int *cnt) {
  printf("counter = %d\n", *cnt);
}

// counter encapsulation
void counter(char *action, ...) {
  static int cnt = 0;// private

  va_list par;
  va_start(par, action);
  int n = *((int *) par);// get argument value
  *((int *) par) = 0;// clear argument value
  va_end(par);

  n = n > 1 ? n : 1;

  #ifdef DEBUGMODE
printf("debug: action = %s, counter = %d, n = %d\n", action, cnt, n);
  #endif

  if (is_init(action))
    init(&cnt);
  else if (is_increment(action))
    increment(&cnt, n); 
  else if (is_decrement(action))
    decrement(&cnt, n);
  else if (is_show(action))
    show(&cnt);
  else
    printf("unsupported action\n");
}

int main() {

  counter("init");                 // counter = 0
  counter("increment");    // counter = 1
  counter("increment");    // counter = 2
  counter("show");              // counter = 2
  counter("increment", 5); // counter = 7
  counter("show");               // counter = 7
  counter("decrement");     // counter = 6
  counter("show");               // counter = 6
  counter("decrement", 3); // counter = 3
  counter("show");               // counter = 3
  counter("init");                  // counter = 0
  counter("show");               // counter = 0
  counter("test");                  // unsupported action

  return 0;
}

Или так

#include <stdio.h>
#include <stdarg.h>

// actions
typedef enum {init, increment, decrement, show, test} actions;

// check requested init action
int is_init(actions action) {
  return action == init;
}

// check requested increment action 
int is_increment(actions action) {
  return action == increment;
}

// check requested decrement action
int is_decrement(actions action) {
  return action == decrement;


// check requested show action 
int is_show(actions action) {
  return action == show;
}

// init counter action
void init_action(int *cnt) {
  *cnt = 0;
}

// increment counter action
void increment_action(int *cnt, int n) {
  (*cnt) += n;
}

// decrement counter action
void decrement_action(int *cnt, int n) {
  (*cnt) -= n;
}

// show counter action
void show_action(const int *cnt) {
  printf("counter = %d\n", *cnt);
}

// counter encapsulation
void counter(actions action, ...) {
  static int cnt = 0; // private

  va_list par;
  va_start(par, action);
  int n = *((int *) par);// get argument value
  *((int *) par) = 0;// clear argument value
  va_end(par);

  n = n > 1 ? n : 1;

  #ifdef DEBUGMODE
  printf("debug: action = %s, counter = %d, n = %d\n", action, cnt, n);
  #endif

  if (is_init(action))
    init_action(&cnt);
  else if (is_increment(action))
    increment_action(&cnt, n); 
  else if (is_decrement(action))
    decrement_action(&cnt, n);
  else if (is_show(action))
    show_action(&cnt);
  else
    printf("unsupported action\n");
}

int main() {

  counter(init);                  // counter = 0
  counter(increment);     // counter = 1
  counter(increment);     // counter = 2
  counter(show);               // counter = 2
  counter(increment, 5); // counter = 7
  counter(show);               // counter = 7
  counter(decrement);     // counter = 6
  counter(show);               // counter = 6
  counter(decrement, 3); // counter = 3
  counter(show);                // counter = 3
  counter(init);                   // counter = 0
  counter(show);                // counter = 0
  counter(test);                   // unsupported action

  return 0;
}

C. For each function independent of data types

При работе на C часто имеешь дело с массивами разного типа. Для вывода содержимого каждой из них нужно реализовать собственные функции. Учитывая, что перегрузка в данном случае не поддерживается, нужно еще и разные имена придумать. Всем известна функция qsort

void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))

которая может работать с массивами абсолютно разного типа. Можно ли реализовать аналогичную универсальную функцию для вывода содержимого массивов так же независимо от типа.  Ниже приведен один из подходов.

#include <stdio.h>
#include <string.h>

#define count(x) sizeof(x) / sizeof(x[0])

typedef struct {
  int id;
  char title[50];
  char author[50];
  char subject[50];
} Book;

void for_each(void *base, size_t num, size_t size, void (*by_item) (void *)) {
  unsigned char *p = (unsigned char *) base;
  unsigned int i = 0;
  for (; i < num; i++) {
    by_item(p + i * size);
  }
}

// show int item
void show_num(void *item) {
  printf("item = %d\n", *((int *) item));
}

// show char item
void show_char(void *item) {
  printf("item = %c\n", *((char *) item));
}

// show Book item
void show_book(void *item) {
  printf("id:%d title:%s author:%s subject:%s\n", 

                   ((Book *) item)->id, 
                        ((Book *) item)->title, 
                              ((Book *) item)->author, 
                                    ((Book *) item)->subject);
}

int main() {
  int nums[] = {1, 2, 3, 4, 5};
  char chars[] = "abcdefgh";
  Book books[] = {
    {11179, "Book_1", "Jon Bredbery", "Tutorial_1"},
    {34454, "Book_2", "Adam Rich", "Tutorial_2"},
    {76899, "Book_3", "Den Swarovsky", "Tutorial_3"}
  };

  for_each(nums, count(nums), sizeof(int), show_num);//show all nums
  for_each(chars, strlen(chars), sizeof(char), show_char);//show all chars
  for_each(books, count(books), sizeof(Book), show_book);//show all books

  return 0;
}


PHP5. Redis. Install redis client (Predis) on Unix/Windows OS

Predis является гибким и полнофункциональным php клиентом для работы с Redis хранилищем. Более подробно с функционалом можно ознакомиться по ссылке:

https://github.com/nrk/predis/wiki

Для того, чтобы задействовать данного клиента, нужно минимум действий.
Склонируйте следующий репозиторий в директорию проекта:

$ git clone git://github.com/nrk/predis.git

или загрузите с данного репозитория архив, на данный момент доступен следующий:

https://github.com/nrk/predis/archive/v1.0.zip

На выходе должна получиться следующая структура

/project
    /index.php
    /predis
        /...
       
Далее в коде регистрируем автозагрузчик классов:

require "predis/autoload.php";
Predis\Autoloader::register();


После чего создаем клиента и работаем с ним:

// для локального подключения
$client = new Predis/Client();
 

// для удаленного подключения
$client = new Predis/Client(array(
    "scheme" => "tcp",
    "host" => "192.168.5.172",
    "port" => 6379
));


Ниже приведен пример использования данного клиента

<?php
require "predis/autoload.php";
Predis\Autoloader::register();

try {
    $client = new Predis/Client();
    $client->set('foo', 'bar');
    $value = $client->get('foo');
    echo $value;
}
catch (Exception $e) {
    die($e->getMessage());
}

?>

Данное мини руководство справедливо как для unix, так и для windows платформ.



oracle v.11.2. Generate new ids for hierarchical query

with
 
  -- source hierarchical test data
  tbl1(id, pid) as (
    select 1, null from dual union all
    select 2, 1 from dual union all
    select 3, 2 from dual union all
    select 4, null from dual union all
    select 5, 4 from dual union all
    select 6, null from dual union all
    select 7, 6 from dual union all
    select 8, 7 from dual union all
    select 9, 8 from dual union all
    select 10, 9 from dual
  ),


 -- source hierarchical test data with generated new ids
 tble2(new_id, id, pid) as (
   select floor(dbms_random.value(1, 1000)) new_id , id, pid
   from tbl1
 )

select
  level
 ,r.id
 ,r.pid
 ,sys_connect_by_path(r.id, '\')
 ,r.new_id
 ,r.new_pid
 ,sys_connect_by_path(r.new_id, '\')
from (
  select
    t2.id
   ,t2.pid
   ,t2.new_id
   ,(select t.new_id from tble2 t where t2.pid = t.id) new_pid
  from tble2 t2
) r
connect by prior r.id = r.pid
start with r.pid is null




Как сгенерировать новые ключи для иерархических записей? Выше представлен один из способов решения данной задачки. Генерация новых ключей, понятное дело приведено для примера, в Вашем случае могут использоваться consequences. Конструкция with позволяет однократно сгенерировать новые ключи и в дальнейшем за счет этого получать доступ к соответствующим родительским ключам.